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

时间:2017-04-05 11:03:49

标签: 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);
}

我正在使用一个测试基类,将_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>();
    }

再次测试非常简单:

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

        // Act & Assert
        Assert.ThrowsException<ArgumentException>(() => _myController.Track(dataItem));
    }

即使ModelState.IsValid缺少必需属性(本例中为true),我发现DataItem Prop3在运行unittest时也是false。使用相同的输入通过Web测试控制器时,验证工作正常(返回ModelState.IsValid ImageView imageView = (ImageView) findViewById(R.id.image_view); imageView.setScaleType(ScaleType.CENTER); )。

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

2 个答案:

答案 0 :(得分:9)

您应该查看使用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);

答案 1 :(得分:7)

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

_myController.ModelState.AddModelError("yourItemFieldHere", "Your validation type here");

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