asp.net core 中的 TryValidateModel 在执行单元测试时抛出空引用异常

问题描述 投票:0回答:5

我正在尝试为 Asp.Net Core Web API 的 ModelState 验证编写单元测试。

我读到,最好的方法是使用

TryValidateModel
函数。但是,每次运行单元测试时,它都会抛出 NullReference 异常。
我发现很多文章都建议
controller.ModelState.AddModelError("","")
,但我对此不感兴趣,因为我相信它超出了真实模型验证的实际目的。

[TestMethod]
public void TestMethod1()
{
    var controller = new TestController();

    controller.Post(new Model());
}


public class TestController : Controller
{
    public IActionResult Post(Model model)
    {
        bool b = TryValidateModel(model)

        return Ok();
    }
}

TryValidateModel(model)
总是从
TryValidateModel(model, prefix)
函数抛出 NullReference 异常。

感谢任何帮助。

c# unit-testing asp.net-core
5个回答
17
投票

这是配置/集成问题。

您可以在 ASP.NET Core 存储库中的 issue 和 github 上的 another 中查看一些附加信息。 但我可以告诉你最简单的修复方法(我用过一次)

var objectValidator = new Mock<IObjectModelValidator>(); objectValidator.Setup(o => o.Validate(It.IsAny<ActionContext>(), It.IsAny<ValidationStateDictionary>(), It.IsAny<string>(), It.IsAny<Object>())); controller.ObjectValidator = objectValidator.Object;
    

4
投票
当我想到如何修复空引用异常(感谢@Egorikas)时,我注意到它仍然没有真正验证模型并且总是返回 true。

我发现我们可以在

Validator

命名空间中使用 
System.ComponentModel.DataAnnotations
 类。

[TestMethod] public void TestMethod1() { var model = new Person(); var validationResultList = new List<ValidationResult>(); bool b1 = Validator.TryValidateObject(model, new ValidationContext(model), validationResultList); }

如果您打算进行 ModelState 验证,您可以直接从 Test 方法本身对其进行验证,而不必调用控制器。

希望这有帮助。


4
投票
基于 Andrew Van Den Brink 的回答,但实际上在 ModelState 中设置了验证错误。

private class ObjectValidator : IObjectModelValidator { public void Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model) { var context = new ValidationContext(model, serviceProvider: null, items: null); var results = new List<ValidationResult>(); bool isValid = Validator.TryValidateObject( model, context, results, validateAllProperties: true ); if (!isValid) results.ForEach((r) => { // Add validation errors to the ModelState actionContext.ModelState.AddModelError("", r.ErrorMessage); }); } }
然后,只需在控制器中设置 ObjectValidator 即可:

controller.ObjectValidator = new ObjectValidator();
    

0
投票
public class ObjectValidator : IObjectModelValidator { private object parameter; public ObjectValidator(object parameter) { this.parameter = parameter; } public void Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model) { var validationContext = new ValidationContext(parameter, null, null); System.ComponentModel.DataAnnotations.Validator.ValidateObject(model, validationContext); } } var model=new {}; // Model to test Controller controller = new Controller(); //Controller to test controller.ObjectValidator = new ObjectValidator(model);
这个会抛出异常


0
投票
我编辑了 Egorikas 的答案以引发错误:

回调的灵感来自于

这个答案回调的使用。

// Code mocking your controller var objectValidator = new Mock<IObjectModelValidator>(); objectValidator.Setup(o => o.Validate(It.IsAny<ActionContext>(), It.IsAny<ValidationStateDictionary>(), It.IsAny<string>(), It.IsAny<object>())).Callback<ActionContext, ValidationStateDictionary, string, object>((actionContext, _, _, _) => actionContext.ModelState.AddModelError("error", "test error")); controller.ObjectValidator = objectValidator.Object;
代码向控制器的验证状态添加了一个错误,这又意味着“TryValidateModel”返回 false。

© www.soinside.com 2019 - 2024. All rights reserved.