我有一个ASP MVC 3应用程序,在我的模型中,我实现了IValidatableObject。
当我的控制器发布创建或编辑时,我显然只想保存模型,如果它有效。
我看到很多博客,帖子和答案都说像
if(!ModelState.IsValid)
{
return View();
}
我的问题。为什么ModelState.IsValid在Controller的单元测试中始终为true?
示例:
[Test]
public void InValidModelsAreNotAdded()
{
var invalidModel = new MyModel() { SomeField = "some data", SomeOtherField = "" };
var result = _controller.Submit(invalidModel);
_repository.AssertWasNotCalled(r => r.Add(Arg.Is.Anything));
}
型号代码:
public class MyModel : IValidatableObject
{
public string SomeField { get; set; }
public string SomeOtherField { get; set; }
public IEnumerable Validate(ValidationContext validationContext)
{
if(string.IsNullOrWhiteSpace(SomeOtherField))
{
yield return
new ValidationResult("Oops invalid.", new[] {"SomeOtherField"});
}
}
}
AssertWasNotCalled总是无法通过此测试。
我完成了测试并注意到此测试的ModelState.IsValid为true。就好像没有调用IValidatableObject.Validate一样。它似乎在我运行项目时起作用,但这并不是测试驱动应用程序的方法。
另外,我意识到我可以在我的示例中使用[Required]
属性,但我的真实代码对它的验证要复杂得多。
思想?
答案 0 :(得分:23)
这是真的,因为你没有调用任何设置为假的东西。
这通常在绑定期间发生,但由于您只是在测试中直接传递模型,因此您完全跳过了该模型。
如果您正在尝试测试验证,请直接执行此操作。如果您尝试在控制器中测试错误路径,则测试的排列可以调用_controller.ModelState.AddModelError( //...
答案 1 :(得分:1)
好吧,试图模拟模型绑定行为,你可以这样做:
public class YourController : Controller
{
//some code
public ViewResult someAction(Model model)
{
try
{
ValidateModel(model);
}
catch
{
// deal with errors
}
}
//some code
}
带有“try catch”块的ValidateModel对我来说更具可读性。但您仍然可以使用方法TryValidateModel
的“if”块希望有所帮助!!