测试ModelState在asp.net mvc中总是有效的
本文关键字:有效 mvc ModelState asp net 测试 | 更新日期: 2023-09-27 18:15:11
在测试控制器的动作时,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);
}
}
And test:
[Test]
public TestInvalidProduct()
{
var product = new Product();
var controller = new ProductController();
controller.Create(product);
//controller.ModelState.IsValid == true
}
当产品没有名称、描述和价格时,为什么modelState是有效的?
当提交的数据绑定到视图模型时进行验证。然后将视图模型传递给控制器。您将跳过第1部分,直接将视图模型传递给控制器。
您可以使用
手动验证视图模型System.ComponentModel.DataAnnotations.Validator.TryValidateObject()
我也遇到过同样的问题,虽然这里接受的答案确实解决了"无验证"问题,但它确实给我留下了一个很大的负面影响:当存在验证错误时,它会抛出一个异常,而不是简单地将ModelState.Invalid
设置为false
。
我只在Web Api 2中测试了这个,所以我不知道什么项目将有这个可用,但是有一个方法ApiController.Validate(object)
,它强制对传递的对象进行验证,并且只将ModelState.IsValid
设置为false
。此外,您还必须实例化Configuration
属性。
将这段代码添加到我的单元测试中允许它工作:
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);
}
现在你知道,你的模型是正确的绑定,你可以继续测试模型与你的控制器在一个单独的测试,以检查它是否返回正确的结果。此外,您可以使用绑定的模型值来测试验证属性。
这样你就可以得到一套完整的测试,如果你的应用程序爆炸了,它会显示在哪个级别上发生了爆炸。
- 创建控制器类的实例。
- 添加模型状态和调用添加模型状态后
-
modelState总是给出false
controller.ModelState.AddModelError("key", "error message"); var invalidStateResult = _controller.Index(); Assert.IsNotNull(invalidStateResult);
使用controller.UpdateModel
或controller.TryUpdateModel
使用控制器的当前ValueProvider绑定一些数据,并在检查ModelState之前触发模型绑定验证。IsValid
如果您想测试验证操作的行为,您可以简单地添加ModelStateError:
ModelState.AddModelError("Password", "The Password field is required");
尝试controller.ViewModel. modelstate。