在AspNetCore上进行单元测试控制器模型验证

And*_*aal 5 c# unit-testing asp.net-core asp.net-core-webapi

在ASPNET核心项目中,我试图创建一些单元测试,以验证我的数据验证逻辑是否正常工作.

我的控制器非常简单:

[HttpPost]
[Route("Track")]
public void Track([FromBody] DataItem item)
{
    if (!ModelState.IsValid) throw new ArgumentException("Bad request");

    _dataItemSaver.SaveData(item);
}
Run Code Online (Sandbox Code Playgroud)

我正在使用一个测试基类,将_myController对象设置为测试中的控制器.

    public ControllerTestBase()
    {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"buildversion.json", optional: true)
            .AddEnvironmentVariables();
        _config = builder.Build();

        var services = new ServiceCollection()
            .AddEntityFrameworkInMemoryDatabase()
            .AddDbContext<MyDbContext>(options =>
            {
                options.UseInMemoryDatabase();
            })
            .AddScoped<IDataItemSaver, DataItemSQLStorageService>()
            .AddScoped<MyController>()
            .Configure<MyConfig>(_config.GetSection(nameof(MyConfig)));

        services
            .AddMvc(mvcOptions =>
                {
                    mvcOptions.Filters.AddService(typeof(GlobalExceptionFilter), 0);
                });

        _additionalDISetupActions?.Invoke(services);

        _serviceProvider = services.BuildServiceProvider();

        _myController = _serviceProvider.GetService<MyController>();
    }
Run Code Online (Sandbox Code Playgroud)

测试再次非常简单:

    [TestMethod]
    public void Prop3Required()
    {
        // Arrange
        var dataItem = new DataItem()
        {
            Prop1 = "Prop1",
            Prop2 = "Prop2"
        };

        // Act & Assert
        Assert.ThrowsException<ArgumentException>(() => _myController.Track(dataItem));
    }
Run Code Online (Sandbox Code Playgroud)

我发现,即使我缺少必需的属性(在本例中)ModelState.IsValid也是true在运行unittest时.当通过网络使用相同的输入测试控制器,确认工作正常(返回的).DataItemProp3falseModelState.IsValid

如何从单元测试中正确触发ASPNET核心逻辑以进行模型状态验证?

小智 10

您应该看看使用ASP.NET Core进行集成测试(https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing),这是一种非常简单的方法来托管您的应用程序测试环境并测试整个管道.
如文档中所述,您可以在测试方法中执行以下操作:

_server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
_client = _server.CreateClient();
// Pass a not valid model 
var response = await _client.PostAsJsonAsync("Track", new DataItem());
Assert.IsFalse(response.IsSuccessStatusCode);
Run Code Online (Sandbox Code Playgroud)

  • 很高兴提到 TestServer 及其集成测试功能,但问题是关于单元测试的问题。 (2认同)

Chr*_*len 7

如果要进行纯单元测试,则需要手动模拟模型状态错误,因为模型状态验证仅在运行时触发.

_myController.ModelState.AddModelError("yourItemFieldHere", "Your validation type here");
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/testing