【问题标题】:How do I unit test model validation in controllers decorated with [ApiController]?如何在用 [ApiController] 装饰的控制器中对模型验证进行单元测试?
【发布时间】:2019-03-21 09:21:47
【问题描述】:

正如this anwerAsp.Net Core 2.1 ApiController does not automatically validate model under unit test 中所指出的,ASP.NET Core 2.1 的 ApiControllerAttribute 为我们提供的自动 ModelState 验证仅在运行时实际请求操作时才有效,而不是通过在单元测试。

但是,当提供不正确的模型时,我仍然想测试我的操作是否真的返回 BadRequestResult。有没有办法做到这一点?我知道我仍然可以手动检查 ModelState.IsValid 是否为假,并自己返回 BadRequest(),但这会破坏自动验证的意义。

毕竟我是手动检查 ModelState.IsValid,还是有办法在单元测试中使用新的 ApiControllerAttribute 模型验证?

【问题讨论】:

  • 我最终制作了一个 AspNetCore 中间件,用于测试模型是否无效,如果是,则在其中返回一个 badrequest。不幸的是,这样做也意味着您只能通过集成测试来测试验证器是否正在工作。
  • 我想我可以让单元测试检查控制器是否用 ApiController 装饰...感觉不对,但最终总比没有测试要好。

标签: unit-testing asp.net-core asp.net-core-webapi asp.net-core-2.1


【解决方案1】:

如果您想验证 api 在数据注释被破坏时返回 badrequest,那么您需要进行 api 集成测试。 一个不错的选择是使用TestServer通过内存客户端运行集成测试

这是一个例子:

//arrange
var b = new WebHostBuilder()
    .UseStartup<YourMainApplication.Startup>()
    .UseEnvironment("development");

var server = new TestServer(b) { BaseAddress = new Uri(url) };
var client = server.CreateClient();
var json = JsonConvert.SerializeObject(yourInvalidModel);
var content = new StringContent(json, Encoding.UTF8, "application/json");

//act
var result = await client.PostAsync("api/yourController", content);

//assert
Assert.AreEqual(400, (int)result.StatusCode);

如果您只需要确保注释设置正确,您可以通过TryValidateObject 方法手动触发验证

var obj = new YourClass();
var context = new ValidationContext(obj);
var results = new List<ValidationResult>();
var valid = Validator.TryValidateObject(obj, context, results, true);

【讨论】:

  • 很好,非常感谢。一个问题:我的启动类声明了一项服务,我在其中包装了所有数据库访问。在单元测试中,我有一个模拟服务,它只是设置并获取一些我检查的测试值。有没有办法让 Startup 在进行集成测试时使用该模拟服务?
  • @Bas 您可以在 Web 主机构建器上调用 .ConfigureTestServices() 来配置要在集成测试时使用的服务。这样,您还可以替换现有的注册。
猜你喜欢
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 2016-04-03
  • 1970-01-01
  • 2017-07-12
  • 1970-01-01
  • 2020-10-29
  • 2014-02-20
相关资源
最近更新 更多