ASP.. NET MVC控制器post方法单元测试:ModelState.有效总是为真
本文关键字:有效 ModelState 单元测试 MVC NET 控制器 post 方法 ASP | 更新日期: 2023-09-27 17:51:11
我已经为ASP编写了我的第一个单元测试。NET MVC web应用程序。所有的工作都很好,它给了我有价值的信息,但我无法测试视图模型中的错误。模型状态。IsValid总是为真,即使某些值没有被填充(空字符串或null)。
我已经读到,当发布的数据映射到模型时,模型验证就会发生,您需要编写一些代码来自己进行模型验证:
- Geek With Blogs
- 我如何测试ModelState?
我已经尝试了链接网页中提供的三个例子,但它似乎不适合我。
一些代码:我viewmodel...
[Required(ErrorMessageResourceName = "ErrorFirstName", ErrorMessageResourceType = typeof(Mui))]
[MaxLength(50)]
[Display(Name = "Firstname", ResourceType = typeof(Mui))]
public string FirstName { get; set; }
...
控制器
...
[HttpPost]
public ActionResult Index(POSViewModel model)
{
Contract contract = contractService.GetContract(model.ContractGuid.Value);
if (!contract.IsDirectDebit.ToSafe())
{
ModelState.Remove("BankName");
ModelState.Remove("BankAddress");
ModelState.Remove("BankZip");
ModelState.Remove("BankCity");
ModelState.Remove("AccountNr");
}
if (ModelState.IsValid)
{
...
contractValidationService.Create(contractValidation);
unitOfWork.SaveChanges();
return RedirectToAction("index","thanks");
}
else
{
return Index(model.ContractGuid.ToString());
}
}
单元测试
posViewModel.FirstName = null;
posViewModel.LastName = "";
...
var modelBinder = new ModelBindingContext()
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => posViewModel, posViewModel.GetType()),
ValueProvider = new NameValueCollectionValueProvider(new System.Collections.Specialized.NameValueCollection(), CultureInfo.InvariantCulture)
};
var binder = new DefaultModelBinder().BindModel(new ControllerContext(), modelBinder);
posController.ModelState.Clear();
posController.ModelState.Merge(modelBinder.ModelState);
ActionResult result = posController.Index(posViewModel);
//Assert
mockContractValidationService.Verify(m => m.Create(It.IsAny<ContractValidation>()), Times.Never);
Assert.IsInstanceOfType(result, typeof(ViewResult));
在视图中,我使用了不显眼的JavaScript验证,它可以工作。
您正在尝试同时测试两种不同的东西。控制器不负责验证模型状态,只负责基于验证结果的不同行为。控制器的单元测试不应该测试验证,那应该在另一个测试中完成。在我看来,你应该有三个单元测试:
- 验证模型验证是否正确的一个
- 用于验证当modelstate有效时控制器是否正确地行为
- 当modelstate无效时,验证控制器是否正确行为的一个
你可以这样做:
1。模型验证
[Test]
public void test_validation()
{
var sut = new POSViewModel();
// Set some properties here
var context = new ValidationContext(sut, null, null);
var results = new List<ValidationResult>();
var isModelStateValid =Validator.TryValidateObject(sut, context, results, true);
// Assert here
}
2。具有无效模型状态的控制器
[Test]
public void test_controller_with_model_error()
{
var controller = new PosController();
controller.ModelState.AddModelError("test", "test");
ActionResult result = posController.Index(new PosViewModel());
// Assert that the controller executed the right actions when the model is invalid
}
3。具有有效modelstate的控制器
[Test]
public void test_controller_with_valid_model()
{
var controller = new PosController();
controller.ModelState.Clear();
ActionResult result = posController.Index(new PosViewModel());
// Assert that the controller executed the right actions when the model is valid
}
我找到了这个解决方案:SO:当我使用Validator时验证不起作用。TryValidateObject与@Kenneth提供的解决方案相结合:
[TestMethod]
public void test_validation()
{
var sut = new POSViewModel();
// Set some properties here
var context = new ValidationContext(sut, null, null);
var results = new List<ValidationResult>();
TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(POSViewModel), typeof(POSViewModel)), typeof(POSViewModel));
var isModelStateValid = Validator.TryValidateObject(sut, context, results, true);
// Assert here
}
如果您有一个包含所有资源的类库,不要忘记在您的测试项目中引用它。