Bas
Bas

Reputation: 2038

How do I unit test model validation in controllers decorated with [ApiController]?

As pointed out in this anwer to Asp.Net Core 2.1 ApiController does not automatically validate model under unit test, the automatic ModelState validation that ASP.NET Core 2.1's ApiControllerAttribute gives us only works when actualyy requestion the action at runtime, not by calling it with an invalid parameter in a unit test.

However, I still want to test if my action actually returns a BadRequestResult when supplying an incorrect model. Is there any way of doing this? I get that I can still manually check if ModelState.IsValid is false, and returning BadRequest() myself, but that kind of defeats the point of the automatic validation.

Am I stuck manually checking ModelState.IsValid after all, or is there a way to make use of the new ApiControllerAttribute model validation in a unit test?

Upvotes: 10

Views: 4036

Answers (1)

Marcus Höglund
Marcus Höglund

Reputation: 16801

If you want to validate that the api's are returning a badrequest when the data annotations are broken then you need to do an api integration test. One nice option is to run the integration tests via an in-memory client using the TestServer

Here's an example:

//arrange
var b = new WebHostBuilder()
    .UseStartup<YourMainApplication.Startup>()
    .UseEnvironment("development");

var server = new TestServer(b) { BaseAddress = new Uri(url) };
var client = server.CreateClient();
var json = JsonConvert.SerializeObject(yourInvalidModel);
var content = new StringContent(json, Encoding.UTF8, "application/json");

//act
var result = await client.PostAsync("api/yourController", content);

//assert
Assert.AreEqual(400, (int)result.StatusCode);

If you only need to make sure that the annotations is proper setup you can manually trigger the validation via the TryValidateObject method

var obj = new YourClass();
var context = new ValidationContext(obj);
var results = new List<ValidationResult>();
var valid = Validator.TryValidateObject(obj, context, results, true);

Upvotes: 12

Related Questions