使用Moq和Mock设置的具有IConfiguration的单元测试控制器返回null

dokyalashot

单元测试Web API的新功能。我正在编写单元测试以测试控制器,而我必须模拟Iconfiguration。appsettings,json有一个名为“ AppSettings”的部分,我正在尝试模拟它。

另外,mock.setup在控制器中返回空值,导致其失败。

这是我的控制器:

    private readonly ILogger _logger;
    private readonly IConfiguration _configuration;
    private readonly ICarPairingTable PairingTable;
    private readonly ICarDealerSettingsTable DealerSettingsTable;
    static AppSettings appSettings = null;
    public CarController(IConfiguration configuration, ICarPairingTable carPairingTable, ICarDealerSettingsTable settingsTable)
    {
        _configuration = configuration;
        appSettings = configuration.Get<AppSettingsModel>().AppSettings;
        PairingTable = carPairingTable;
        DealerSettingsTable = settingsTable;
    }

    [HttpGet]
    public ActionResult Get(string id){
        string DealerId ="";


                DealerId = PairingTable.GetDealerId(id).Result;
                if (string.IsNullOrEmpty(DealerId))
                {
                    result = new ReturnResult
                    {
                        status = "Fail",
                        data = "ID is invalid"
                    };
                    return NotFound(result);
                }



            SettingsInfo info = DealerSettingsTable.GetSettingsInfo(DealerId).Result;
            if (info == null)
            {
                result = new ReturnResult
                {
                    status = "Fail",
                    data = "Not Found
                };
                return NotFound(result);

            }
            result = new ReturnResult
            {
                status = "Success",
                data = info
            };
            return Ok(result);
    }

这是我的单元测试:

   [Fact]
    public void Test1()
    {
        var mockConfig = new Mock<IConfiguration>();
        var configurationSection = new Mock<IConfigurationSection>();

        configurationSection.Setup(a => a.Value).Returns("testvalue");
        mockConfig.Setup(a => a.GetSection("AppSettings")).Returns(configurationSection.Object);

        var mock1 = new Mock<ICarPairingTable>();

        mock1.Setup(p => p.GetDealerId("456")).ReturnsAsync("123");
        var mock2 = new Mock<ICarDealerSettingsTable>();
        SettingsInfo mockSettings = new SettingsInfo()
        {
            DealerId = "123",

            Name="Dealer1"
        };
        mock2.Setup(p => p.GetSettingsInfo("123")).ReturnsAsync(()=>mockSettings);

        CarController controller = new CarController(mockConfig.Object,  mock1.Object, mock2.Object);
        var result = controller.Get("456");

        //Dont know what to assert

    }

编写了单元测试,但不确定我的方法是否正确,将不胜感激。

恩科西

这更多的是涉及XY问题的设计问题

真的不应该注射IConfiguration根据控制器使用配置的方式,您应该在启动时向服务集合注册设置

Startup.ConfigureServices

//...

AppSettings appSettings = Configuration.Get<AppSettingsModel>().AppSettings;

services.AddSingleton(appSettings);

//...

并明确地将设置注入控制器

//...

private readonly AppSettings appSettings = null;
public CarController(AppSettings appSettings , ICarPairingTable carPairingTable, ICarDealerSettingsTable settingsTable) {
    this.appSettings = appSettings;
    PairingTable = carPairingTable;
    DealerSettingsTable = settingsTable;
}

//...

因此,现在在对控制器进行单元测试时,您可以初始化所需类的实例,并在执行单元测试时提供该实例。

参考显式依赖原则

您似乎还混在一起了async-await和阻止类似的调用.Result

我建议您将动作一直保持异步

[HttpGet]
public async Task<ActionResult> Get(string id){
    string DealerId = await PairingTable.GetDealerId(id);
    if (string.IsNullOrEmpty(DealerId)) {
        var result = new ReturnResult {
            status = "Fail",
            data = "ID is invalid"
        };
        return NotFound(result);
    }

    SettingsInfo info = await DealerSettingsTable.GetSettingsInfo(DealerId);
    if (info == null) {
        var result = new ReturnResult {
            status = "Fail",
            data = "Not Found"
        };
        return NotFound(result);
    }
    var result = new ReturnResult {
        status = "Success",
        data = info
    };
    return Ok(result);
}

参考Async / Await-异步编程最佳实践

这样,最终可以正确安排单元测试以验证预期的行为

[Fact]
public async Task Should_Return_Ok_ReturnRsult() {
    //Arrange
    var id = "456";
    var dealerId = "123";
    SettingsInfo expected = new SettingsInfo() {
        DealerId = dealerId,
        Name="Dealer1"
    };

    var pairingMock = new Mock<ICarPairingTable>();
    pairingMock.Setup(p => p.GetDealerId(id)).ReturnsAsync(dealerId);

    var dealerSettingsMock = new Mock<ICarDealerSettingsTable>();
    dealerSettingsMock.Setup(p => p.GetSettingsInfo(dealerId)).ReturnsAsync(() => expected);

    CarController controller = new CarController(new AppSettings(),  pairingMock.Object, dealerSettingsMock.Object);

    //Act
    var actionResult = await controller.Get(id);
    var actual = actionResult as OkObjectResult;

    //Assert (using FluentAssertions)

    actual.Should().NotBeNull();

    actual.Value.Should().BeOfType<ReturnResult>();

    var actualResult = actual.Value as ReturnResult;

    actualResult.data.Should().BeEquivalentTo(expected);        
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用 Moq 对具有三个依赖项的 MVC 控制器进行单元测试

使用 xunit 和 moq 进行 net core api 控制器单元测试

单元测试控制器,在控制器中具有$ state.go方法

使用Moq对MVC6中的控制器路由功能进行单元测试

如何使用 Moq 对 WEB API 控制器异常进行单元测试

使用 moq 对 Web API 控制器 actualResult 进行单元测试的行为与预期不符

MOQ对象设置范围/上下文因构建器模式单元测试和Web API控制器而丢失

为什么在单元测试中从控制器转换结果返回 null?

在单元测试中动态设置 Yii 控制器

返回PagedResources的单元测试Spring MVC控制器

返回IActionResult的单元测试控制器方法

如何对返回模型的控制器进行单元测试?

返回ContentResult列表对象的单元测试控制器

单元测试-断言控制器操作返回的对象

具有Scala的Play 2框架中的单元测试控制器

ASP.NET MVC5:对具有会话的控制器进行单元测试

Spring MVC控制器单元测试:如何设置私有实例布尔字段?

如何使用JUnit单元测试JavaFX控制器

对使用Moment JS的控制器进行单元测试

尝试使用 $state 对控制器进行单元测试

如何使用$ state构造控制器的单元测试?

使用 GetUserASync (User) 的单元测试控制器

使用NUnit进行单元测试DateTime控制器

如何使用 spring boot 和 mockito 对控制器方法进行单元测试

使用Node.js,Gulp.js和Mocha单元测试angularjs控制器

使用Spring Boot,Kotlin和Junit进行休息控制器单元测试

Kubernetes控制器的单元测试

角单元测试-控制器

休息控制器单元测试