[ACCEPTED]-How can I test ModelState?-asp.net-mvc
You don't have to use a Mock if you're using 2 the Repository Pattern for your data, of 1 course.
Some examples: http://www.singingeels.com/Articles/Test_Driven_Development_with_ASPNET_MVC.aspx
// Test for required "FirstName".
controller.ViewData.ModelState.Clear();
newCustomer = new Customer
{
FirstName = "",
LastName = "Smith",
Zip = "34275",
};
controller.Create(newCustomer);
// Make sure that our validation found the error!
Assert.IsTrue(controller.ViewData.ModelState.Count == 1,
"FirstName must be required.");
//[Required]
//public string Name { get; set; }
//[Required]
//public string Description { get; set; }
ProductModelEdit model = new ProductModelEdit() ;
//Init ModelState
var modelBinder = new ModelBindingContext()
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
() => model, model.GetType()),
ValueProvider=new NameValueCollectionValueProvider(
new NameValueCollection(), CultureInfo.InvariantCulture)
};
var binder=new DefaultModelBinder().BindModel(
new ControllerContext(),modelBinder );
ProductController.ModelState.Clear();
ProductController.ModelState.Merge(modelBinder.ModelState);
ViewResult result = (ViewResult)ProductController.CreateProduct(null,model);
Assert.IsTrue(result.ViewData.ModelState["Name"].Errors.Count > 0);
Assert.True(result.ViewData.ModelState["Description"].Errors.Count > 0);
Assert.True(!result.ViewData.ModelState.IsValid);
0
For testing Web API, use the Validate method on 1 the controller:
var controller = new MyController();
controller.Configuration = new HttpConfiguration();
var model = new MyModel();
controller.Validate(model);
var result = controller.MyMethod(model);
Ran into this problem for .NetCore 2.1 Here's 1 my solution:
Extension Method
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace MyExtension
{
public static void BindViewModel<T>(this Controller controller, T model)
{
if (model == null) return;
var context = new ValidationContext(model, null, null);
var results = new List<ValidationResult>();
if (!Validator.TryValidateObject(model, context, results, true))
{
controller.ModelState.Clear();
foreach (ValidationResult result in results)
{
var key = result.MemberNames.FirstOrDefault() ?? "";
controller.ModelState.AddModelError(key, result.ErrorMessage);
}
}
}
}
View Model
public class MyViewModel
{
[Required]
public string Name { get; set; }
}
Unit Test
public async void MyUnitTest()
{
// helper method to create instance of the Controller
var controller = this.CreateController();
var model = new MyViewModel
{
Name = null
};
// here we call the extension method to validate the model
// and set the errors to the Controller's ModelState
controller.BindViewModel(model);
var result = await controller.ActionName(model);
Assert.NotNull(result);
var viewResult = Assert.IsType<BadRequestObjectResult>(result);
}
This not only let's you check that the error 5 exists but also checks that it has the exact 4 same error message as expected. For example 3 both of these parameters are Required so 2 their error message shows as "Required".
Model 1 markup:
//[Required]
//public string Name { get; set; }
//[Required]
//public string Description { get; set; }
Unit test code:
ProductModelEdit model = new ProductModelEdit() ;
//Init ModelState
var modelBinder = new ModelBindingContext()
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
() => model, model.GetType()),
ValueProvider=new NameValueCollectionValueProvider(
new NameValueCollection(), CultureInfo.InvariantCulture)
};
var binder=new DefaultModelBinder().BindModel(
new ControllerContext(),modelBinder );
ProductController.ModelState.Clear();
ProductController.ModelState.Merge(modelBinder.ModelState);
ViewResult result = (ViewResult)ProductController.CreateProduct(null,model);
Assert.IsTrue(!result.ViewData.ModelState.IsValid);
//Make sure Name has correct errors
Assert.IsTrue(result.ViewData.ModelState["Name"].Errors.Count > 0);
Assert.AreEqual(result.ViewData.ModelState["Name"].Errors[0].ErrorMessage, "Required");
//Make sure Description has correct errors
Assert.IsTrue(result.ViewData.ModelState["Description"].Errors.Count > 0);
Assert.AreEqual(result.ViewData.ModelState["Description"].Errors[0].ErrorMessage, "Required");
Adding to the great answers above, check 7 out this fantastic use of the protected 6 TryValidateModel method within the Controller 5 class.
Simply create a test class inheriting 4 from controller and pass your model to the 3 TryValidateModel method. Here's the link: http://blog.icanmakethiswork.io/2013/03/unit-testing-modelstate.html
Full 2 credit goes to John Reilly and Marc Talary 1 for this solution.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.