如何在动作过滤器中使用参数验证对MVC控制器进行单元测试?

时间:2018-04-20 13:35:29

标签: c# unit-testing fluentvalidation asp.net-mvc-filters

我们有一个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)以确保管道正常运行。在这篇文章中,我想讨论围绕从单元测试方法传递给控制器​​的无效参数的问题。

3 个答案:

答案 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核心集成测试框架太重了,它可以测试整个流程,而不仅仅是模型绑定。我们需要一个模型绑定集成测试框架,运行它可以断言模型状态是否有效,而不关心实际的控制器动作结果。也许我们可以自己写一个。