我正在尝试为 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 异常。
感谢任何帮助。
这是配置/集成问题。
您可以在 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;
我发现我们可以在
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 方法本身对其进行验证,而不必调用控制器。
希望这有帮助。
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();
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);
这个会抛出异常
回调的灵感来自于
这个答案回调的使用。
// 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。