【问题标题】:Unit Test: Mocked service returns default boolean (false) despite Returns() set to true. C# xunit moq单元测试:尽管 Returns() 设置为 true,但模拟服务返回默认布尔值 (false)。 C# xunit 最小起订量
【发布时间】:2021-10-27 14:03:35
【问题描述】:

我被要求在 xunit 中使用 moq(C# .Net Core app 3.1)对以下控制器进行单元测试:

    private readonly IConfigService _configService;
    private readonly IOptions<ApiVersion> _apiVersionSettings;
    private readonly IOptions<MinRequiredDatabaseVersion> _minRequiredDatabaseVersion;

    public InfoController(IConfigService configService, IOptions<ApiVersion> apiVersionSettings, IOptions<MinRequiredDatabaseVersion> minRequiredDatabaseVersion)
    {
        _configService = configService;
        _apiVersionSettings = apiVersionSettings;
        _minRequiredDatabaseVersion = minRequiredDatabaseVersion;
    }

    [HttpGet]
    [ProducesResponseType(typeof(ApplicationVersionDto), 200)]
    [ProducesResponseType(typeof(BadRequestResult), 400)]
    public IActionResult GetVersions()
    {
        // get db version
        var dbVersion = _configService.GetDbVersions();
        // get api version
        var apiVersion = _apiVersionSettings.Value.Version;
        var minReqiredDbVersion = new MinRequiredDataVersion(_minRequiredDatabaseVersion.Value.Major, _minRequiredDatabaseVersion.Value.Minor, _minRequiredDatabaseVersion.Value.BuildNumber);

        var isDatabaseRightVersion = _configService.hasWebSolutionTheRightDatabase(dbVersion, minReqiredDbVersion);
        string currentDbVersion = dbVersion.MajorVersion + "." + dbVersion.MinorVersion + "." + dbVersion.BuildNumber;
        string minDbVersion = minReqiredDbVersion.MajorVersion + "." + minReqiredDbVersion.MinorVersion + "." + minReqiredDbVersion.BuildNumber;
        if (!isDatabaseRightVersion) 
            throw new CustomGisException(CustomGisExceptionName.ArgumentException, 202011101419083007, $"Update the database! current database version {currentDbVersion}, but should have been min. {minDbVersion}", $"Update the database! current database version {currentDbVersion}, but should have been min. {minDbVersion}");

        var result = new ApplicationVersionDto(dbVersion, apiVersion);
        return Json(result);
    }

设置模拟后,模拟的数据库版本服务 (_minRequiredDatabaseVersion) 返回默认布尔值 false,即使模拟设置为返回 true,表示某些东西是梨形的:

    [Fact]
    public void GetVersionsGet_ReturnsJsonResult_WhenInvoked()
    {
        // Arrange
        var mockVwCurrentVersionInfo = Mock.Of<VwCurrentVersionInfo>(x => x.BuildNumber == 988 && x.MajorVersion == 988 && x.MinorVersion == 988);
        fixture.mockApiVersion.SetupGet(o => o.Value).Returns(new ApiVersion(){});
        fixture.mockMinRequiredDatabaseVersion.SetupGet(o => o.Value).Returns(new MinRequiredDatabaseVersion(){
            Major=888,
            Minor=888,
            BuildNumber=888});
        fixture.mockConfigService.Setup(x => x.GetDbVersions()).Returns(mockVwCurrentVersionInfo);
        fixture.mockConfigService.Setup(x => x.hasWebSolutionTheRightDatabase(mockVwCurrentVersionInfo, fixture.mockMinRequiredDataVersion.Object)).Returns(true);

        // Act
        var result = fixture.controller.GetVersions();
        var jsonResult = result as JsonResult;

        // Assert
        // Assertions here.
    }

调试时,我到达控制器中的 if(!isDatabaseRightVersion) 行,这会引发异常。

如何在这个模拟服务中返回布尔值 true?

这是我的固定装置:

public InfoController controller;
public Mock<IConfigService> mockConfigService;
public Mock<IOptions<ApiVersion>> mockApiVersion;
public Mock<IOptions<MinRequiredDatabaseVersion>> mockMinRequiredDatabaseVersion;
public Mock<VwCurrentVersionInfo> mockVwCurrentVersionInfo;
public Mock<MinRequiredDataVersion> mockMinRequiredDataVersion;
public int vurderingsejendomIdToBeFound;

public InfoFixture()
{
    // Mock services and their setups.
    mockConfigService = new Mock<IConfigService>();
    mockApiVersion = new Mock<IOptions<ApiVersion>>();
    mockMinRequiredDatabaseVersion = new Mock<IOptions<MinRequiredDatabaseVersion>>();
    mockVwCurrentVersionInfo = new Mock<VwCurrentVersionInfo>();
    mockMinRequiredDataVersion = new Mock<MinRequiredDataVersion>();
    mockMinRequiredDataVersion.Object.MajorVersion = 5;
    mockMinRequiredDataVersion.Object.MinorVersion = 5;
    mockMinRequiredDataVersion.Object.BuildNumber = 5;

    // Controller
    controller = new InfoController(mockConfigService.Object, mockApiVersion.Object, mockMinRequiredDatabaseVersion.Object);
}

public void Dispose() {}

提前感谢您的宝贵反馈。

【问题讨论】:

  • 我猜minReqiredDbVersion != fixture.mockMinRequiredDataVersion.Object

标签: c# unit-testing moq xunit


【解决方案1】:

在您的设置中

   fixture.mockConfigService
    .Setup(x => x.hasWebSolutionTheRightDatabase(mockVwCurrentVersionInfo, fixture.mockMinRequiredDataVersion.Object))
    .Returns(true);

fixture.mockMinRequiredDataVersion.Object 不等于 minReqiredDbVersion

作为一个选项,您可以使用It.IsAny&lt;T&gt; 而不是fixture.mockMinRequiredDataVersion.Object

      fixture.mockConfigService
    .Setup(x => x.hasWebSolutionTheRightDatabase(mockVwCurrentVersionInfo,It.IsAny< MinRequiredDataVersion >() ))
    .Returns(true);

这种模拟方式适用于MinRequiredDataVersion 的任何实例

我需要确保 minReqiredDbVersion 具有特定版本,您可以通过回调捕获该参数:

MinRequiredDatabaseVersion capturedMinReqiredDbVersion = null;

fixture.mockConfigService
        .Setup(x => x.hasWebSolutionTheRightDatabase(mockVwCurrentVersionInfo,It.IsAny< MinRequiredDataVersion >() ))
        .Callback( (dbVersion, minReqiredDbVersion) => {capturedMinReqiredDbVersion = minReqiredDbVersion; })  
        .Returns(true);

// Assert
// Assert capturedMinReqiredDbVersion here 

【讨论】:

  • 谢谢尤金 - 太棒了。如果您愿意,请为您提供有关回调的快速解决方案:如何在没有委托推断的情况下使用回调? (我得到以下信息:功能“推断的委托类型”在 C# 8.0 中不可用。请使用 10.0 或更高版本的语言。)。
  • 我更新了答案中的代码。在回调中,您可以将参数捕获到某个变量中,然后稍后在您的断言部分中断言捕获的变量。它对您的错误有帮助吗?
猜你喜欢
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
  • 2016-08-02
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2014-03-23
  • 2015-09-19
相关资源
最近更新 更多