测试ModelState在asp.net mvc中始终有效

在测试控制器的操作时,ModelState始终有效。

public class Product { public int Id { get; set; } [Required] [StringLength(10)] public string Name { get; set; } [Required] public string Description { get; set; } [Required] public decimal Price { get; set; } } 

和我的控制器。

 public class ProductController : Controller { [HttpPost] public ActionResult Create(Product product) { if (ModelState.IsValid) { // Do some creating logic... return RedirectToAction("Display"); } return View(product); } } 

并测试:

 [Test] public TestInvalidProduct() { var product = new Product(); var controller = new ProductController(); controller.Create(product); //controller.ModelState.IsValid == true } 

当产品没有名称,描述和价格时,为什么modelState有效?

当发布的数据绑定到视图模型时,将进行validation。 然后将视图模型传递给控制器​​。 您正在跳过第1部分并将视图模型直接传递到控制器中。

您可以使用手动validation视图模型

 System.ComponentModel.DataAnnotations.Validator.TryValidateObject() 

我遇到了同样的问题 ,虽然这里接受的答案确实解决了“无validation”问题,但确实给我带来了一个很大的负面影响:当有validation错误而不是简单地设置ModelState.Invalid时会抛出exceptionModelState.Invalidfalse

我只在Web Api 2中对此进行了测试,因此我不知道哪些项目可用,但是有一个方法ApiController.Validate(object)强制对传递的对象进行validation,并且只将ModelState.IsValid设置为false 。 此外,您还必须实例化Configuration属性。

将此代码添加到我的unit testing允许它工作:

 userController.Configuration = new HttpConfiguration(); userController.Validate(addressInfo); 

另一个注意事项。 您应该实际测试控制器返回的内容以及返回的ActionResult是您所期望的。 测试ModelBinder应该单独完成。

比方说,您想切换到自定义模型绑定器。 您可以将ModelBinder测试重用于您正在创建的新ModelBinder。 如果您的业务规则保持不变,您应该能够直接重用相同的测试。 但是,如果混合使用Controller测试和ModelBinder测试并且测试失败,则无法知道问题是在Controller还是ModelBinder中。

假设你测试你的模型绑定是这样的:

 [Test] public void Date_Can_Be_Pulled_Via_Provided_Month_Day_Year() { // Arrange var formCollection = new NameValueCollection { { "foo.month", "2" }, { "foo.day", "12" }, { "foo.year", "1964" } }; var valueProvider = new NameValueCollectionValueProvider(formCollection, null); var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(FwpUser)); var bindingContext = new ModelBindingContext { ModelName = "foo", ValueProvider = valueProvider, ModelMetadata = modelMetadata }; DateAndTimeModelBinder b = new DateAndTimeModelBinder { Month = "month", Day = "day", Year = "year" }; ControllerContext controllerContext = new ControllerContext(); // Act DateTime result = (DateTime)b.BindModel(controllerContext, bindingContext); // Assert Assert.AreEqual(DateTime.Parse("1964-02-12 12:00:00 am"), result); } 

既然您知道,您的模型是正确的,您可以继续使用您的控制器在单独的测试中测试模型,以检查它是否返回正确的结果。 此外,您可以使用绑定的模型值来测试validation属性。

通过这种方式,您可以获得一整套测试,如果您的应用程序爆炸,将会显示实际执行的级别。 模型绑定,控制器或validation。

  1. 创建控制器类的实例。
  2. 添加模型状态并调用添加模型状态后
  3. modelState总是给出错误

     controller.ModelState.AddModelError("key", "error message"); var invalidStateResult = _controller.Index(); Assert.IsNotNull(invalidStateResult); 

在检查ModelState.IsValid之前,使用controller.UpdateModelcontroller.TryUpdateModel来使用控制器的当前ValueProvider绑定一些数据并触发模型绑定validation

如果要测试validation操作的行为,可以简单地添加ModelStateError:

 ModelState.AddModelError("Password", "The Password field is required"); 

尝试控制器。 ViewModel .ModelState.IsValid而不是controller.ModelState.IsValid。