使用 FluentValidation 如何在控制器中使用 validationContext 进行测试

Posted

技术标签:

【中文标题】使用 FluentValidation 如何在控制器中使用 validationContext 进行测试【英文标题】:With FluentValidation how can I test using validationContext within a controller 【发布时间】:2021-11-19 15:45:40 【问题描述】:

我设置了一个验证器,它需要使用正在验证的视图模型之外的值。所以要做到这一点,我使用 ValidationContext 并分配 RootContextData,然后在控制器中调用 validate 方法,如果它返回错误,我将它添加到模型状态。这一切都很好,但我不知道如何测试它,或者这可能表明我没有以最好的方式完成它。

例如验证者:

RuleFor(x => x.StartDate.Date.Day)
    .Custom((day, context) =>
    
        if (!context.RootContextData.TryGetValue("TargetDate", out var targetDate)) return;
        
        var dateVm = context.InstanceToValidate;
        if (DatesHelper.SourceDateStringIsGreaterThanTargetDateString(
            dateVm.StartDate.DateInputAsString(),
            targetDate as string) == true)
        
            context.AddFailure("The Start date must be on or before the target date for the action");
        
    );

然后在控制器中..

. . .

var repositoryResult = customerRepo.Result;
if (!ModelState.IsValid)

    return View(vm);

var validationContext = new ValidationContext<StartDateViewModel>(vm)

    RootContextData =
    
        ["TargetDate"] = repositoryResult.Dates.Target
    
;
var validator = new StartDateValidator();
var validationResult = await validator.ValidateAsync(validationContext);
if (!validationResult.IsValid)

    ModelState.AddModelError("StartDate.Date.Day", validationResult.Errors.First().ErrorMessage);
    return View(vm);


. . .

显然,我可以只传入一个带有错误日期的视图模型,这会标记这一点,但感觉就像我正在测试控制器中的验证器。我真正想做的(我认为)是传递一个具有任意日期的视图模型,让验证器在该规则上失败,然后断言错误已添加到模型状态。任何帮助表示赞赏。

-珍妮

【问题讨论】:

【参考方案1】:

我认为您可以做的是测试控制器逻辑。 一个例子可能是这样的:

[Test]
public void IndexPost_AddModelStateError_WhenInvalidData()

  var controller = new HomeController();
  var vm = ... //Test Data
  
  var result = controller.Index(vm) as ViewResult;  

  Assert.IsTrue(result.ViewData.ModelState["StartDate.Date.Day"].Errors.Any());          

Here你可以找到微软关于测试控制器逻辑的文档

【讨论】:

我应该说,是的,这是我正在努力测试的控制器。您的方法的问题是我必须提供会触发验证的测试数据,因此如果有意义的话,就不会真正孤立地测试控制器。这就是重点,但我想我可以做到这一点,不要想太多!谢谢 @Blingers:你不能单独测试控制器,因为它依赖于视图模型。所以是的,您必须提供“测试数据”,因为这是控制器的依赖项,以传递给 Index(...) 方法的视图模型的形式。

以上是关于使用 FluentValidation 如何在控制器中使用 validationContext 进行测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Web API 中使用 FluentValidation 执行异步 ModelState 验证?

使用 WebApi [Route] 属性时 FluentValidation 不起作用

FluentValidation 返回错误时如何返回自定义响应?

在 .NET 中使用 FluentValidation 进行参数验证

FluentValidation/MVC/ASP Identity:验证模型时如何获取当前用户 ID?

在对话框中使用 FluentValidation 和 MudBlazor 进行表单验证