问题
I have tried to make this work and made many google/stackoverflow searches with no luck at all.
I have a simple Model:
public class MovieModel
{
public string Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
}
A method in the controller:
// POST: api/Movies
public IHttpActionResult Post([FromBody]MovieModel movieModel)
{
if (ModelState.IsValid)
{
//Code
}
}
And a test method (is an integration test, but the same would happen in unit tests):
[TestMethod]
public void MoviesController_Post_Without_Name()
{
// Arrange
var model = new MovieModel();
model.Name = "";
// Act
var result = controller.Post(model);
// Assert
Assert.IsInstanceOfType(result, typeof(InvalidModelStateResult));
Assert.AreEqual(6, controller.Get().Count());
}
Despite the fact that the model is clearly invalid it always evaluates the IsValid property to true.
I tried many approaches so far without success.
回答1:
Your solution probably works, but a better way is using ApiController.Validate method.
public void MoviesController_Post_Without_Name()
{
// Arrange
var model = new MovieModel();
model.Name = "";
// Act
controller.Validate(model); //<---- use the built-in method
var result = controller.Post(model);
// Assert
Assert.IsInstanceOfType(result, typeof(InvalidModelStateResult));
Assert.AreEqual(6, controller.Get().Count());
}
回答2:
Thanks to this site, I found out the solution:
private void SimulateValidation(object model)
{
// mimic the behaviour of the model binder which is responsible for Validating the Model
var validationContext = new ValidationContext(model, null, null);
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(model, validationContext, validationResults, true);
foreach (var validationResult in validationResults)
{
this.controller.ModelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
}
}
And including one line in the test method like this:
public void MoviesController_Post_Without_Name()
{
// Arrange
var model = new MovieModel();
model.Name = "";
// Act
SimulateValidation(model);
var result = controller.Post(model);
// Assert
Assert.IsInstanceOfType(result, typeof(InvalidModelStateResult));
Assert.AreEqual(6, controller.Get().Count());
}
Hope that helps someone, it would have saved me some hours hunting the web.
回答3:
This worked for me:
public MyResultData Post([FromBody] MyQueryData queryData)
{
if (!this.Request.Properties.ContainsKey("MS_HttpConfiguration"))
{
this.Request.Properties["MS_HttpConfiguration"] = new HttpConfiguration();
}
this.Validate(queryData);
if (ModelState.IsValid)
{
DoSomething();
}
}
Also check out this question: Validate fails in unit tests
回答4:
On WebAPI 5.2.7:
[TestMethod]
public void MoviesController_Post_Without_Name()()
{
// Arrange
var model = new MovieModel();
model.Name = "";
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
controller.Validate(model);
// Act
var result = controller.Post(model);
// Assert
...
This article helped me: https://www.c-sharpcorner.com/article/unit-testing-controllers-in-web-api/
来源:https://stackoverflow.com/questions/37558049/modelstate-isvalid-always-true-when-testing-controller-in-asp-net-mvc-web-api