我们有一个MVC.NET核心Web API应用程序,它使用动作过滤器来验证控制器方法的参数。
对于验证,我们使用FluentValidation框架。在动作过滤器中,我们找到IValidator<TModel>
,其中TModel
是控制器动作的参数,例如:
public async Task<IActionResult> Post([FromBody] TModel model)
{
}
在过滤器的OnActionExecuting(ActionExecutingContext context)
中,我们找到了正确的验证器(IValidator<TModel>
),验证了参数(context.ActionArguments
),如果验证失败,我们通过将验证结果分配到context.Result
- 这意味着执行永远不会到达控制器。
基本原理类似于将FluentValidation连接到MVC的ModelState验证管道,但我们需要一些额外的东西,所以我们手动完成。
我们想对控制器和验证器进行单元测试。问题是单元测试控制器。在测试设置中,我们实例化控制器并调用其中一个方法。现在在生产环境中,参数将始终得到验证,并且只有在参数有效时才能实际进入控制器方法。但是在对控制器进行单元测试时,我们可以轻松地传递无效参数并获得意外行为。
原则上,有没有办法解决这个问题?或者我是否真的需要确保在测试方法中将有效参数传递给控制器?
编辑:
我们还计划进行集成测试(最有可能使用.NET Core的TestServer)以确保管道正常运行。在这篇文章中,我想讨论围绕从单元测试方法传递给控制器的无效参数的问题。
答案 0 :(得分:0)
首先对验证器进行单元测试,以便明确定义哪些参数有效,哪些参数无效。
然后,正如您在问题中建议的那样,您只能获取有效输入并专注于它们以对控制器进行单元测试。
最后,您可以使用有效和无效参数创建一些集成测试。
答案 1 :(得分:0)
您需要在ASP.NET Core中编写集成测试 请参阅链接:https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing?view=aspnetcore-2.0
主要目标:您测试相同的网络API,但它会在您的测试中托管。
答案 2 :(得分:0)
我同意Nkosi在评论中所说的,因为required属性不是控制器直接使用的,而是框架modelbinder用来验证的(fluent验证也是基于此的),所以单独调用控制器方法是不行的单元测试此属性是否存在。它必须与框架进行集成测试。但是asp.net核心集成测试框架太重了,它可以测试整个流程,而不仅仅是模型绑定。我们需要一个模型绑定集成测试框架,运行它可以断言模型状态是否有效,而不关心实际的控制器动作结果。也许我们可以自己写一个。