执行单元测试时,asp.net核心中的TryValidateModel引发Null参考异常

时间:2018-08-09 18:08:05

标签: c# unit-testing asp.net-core

我正在尝试编写用于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异常。

感谢任何帮助。

4 个答案:

答案 0 :(得分:1)

这是配置/集成问题。

您可以在github上的issue in ASP.NET Core repoanother one中看到一些其他信息。 但是我可以告诉您最简单的修复方法(我使用过一次)

        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;

答案 1 :(得分:1)

由于@Egorikas,我弄清楚了如何解决Null引用异常,我注意到它实际上并没有验证模型,并且始终返回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方法本身进行验证,而不必调用控制器。

希望这会有所帮助。

答案 2 :(得分:1)

基于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();

答案 3 :(得分: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);

这将引发异常