Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

ModelState.IsValid show true for invalid entry on Test

I have class city:

public class City
{
    public int Id { get; set; }
    [Required(ErrorMessage = "This field is required (server validation)")]
    public string Name { get; set; }
    [Range(1, 100000000, ErrorMessage = "ZIP must be greater than 1 and less than 100000000 (server validation)")]
    public int ZIP { get; set; }
    [Range(1, 2000000000, ErrorMessage = "Population must be between 1 and 2B (server validation)")]
    public int Citizens { get; set; }
    public int CountryId { get; set; }
    public Country Country { get; set; }
}

I have in controller post action for add city:

[HttpPost]
public IActionResult PostCity(City city)
{
       if (!ModelState.IsValid)
       {
           return BadRequest(ModelState);
       }
       _cityRepository.Add(city);
       return CreatedAtAction("GetCity", new { id = city.Id }, city);
}

and I have test for invalid model:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[Fact]
public void PostCity_InvalidModel_ReturnsBadRequest()
{
   // Arrange
   City city = new City() { Id=15, Name = "", ZIP = 0, CountryId = 1, Citizens = 0 };
   var mockRepository = new Mock<ICityRepositroy>();
   var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile(new CityProfile()));

   IMapper mapper = new Mapper(mapperConfiguration);
   var controller = new CitysController(mockRepository.Object, mapper);

    // Act
    var actionResult = controller.PostCity(city) as BadRequestResult;

   // Assert
   Assert.NotNull(actionResult);
}

I debug test and I always get modelState.IsValid = true. When I try in postman to send invalid request, server validation works fine. Why my validation doesn’t work in my test? ASP .Net Core framework is 5.0.

>Solution :

Your test call the method controller.PostCity(city) directly, while in the web server, when calling the endpoint, a whole bunch of middle ware is triggered and executed first.

One of this being the modelbinder, which I believe also performs the model validation.

So this will not work, because calling the ModelState.IsValid without any further initialization, causes it to return true as by default:

var controller = new CitysController(mockRepository.Object, mapper);

// Act
var actionResult = controller.PostCity(city) as BadRequestResult;

In stead you either need to connect the proper validation mechanism of the model, or even better (IMO) use the test web server which can do this in an easy controllable way.

Here’s basically how to do it, but I recommend you to read some of the following articles as well (source: MSDN):

public class PrimeWebDefaultRequestShould
{
    private readonly TestServer _server;
    private readonly HttpClient _client;

    public PrimeWebDefaultRequestShould()
    {
        // Arrange
        _server = new TestServer(new WebHostBuilder()
           .UseStartup<Startup>());
        _client = _server.CreateClient();
    }

    [Fact]
    public async Task ReturnHelloWorld()
    {
        // Act
        var response = await _client.GetAsync("/");
        response.EnsureSuccessStatusCode();
        var responseString = await response.Content.ReadAsStringAsync();
        // Assert
        Assert.Equal("Hello World!", responseString);
    }
}

In the code above you’ll need to replace the likes like EnsureSuccessStatusCode with you actual BadRequest test case.

Some additional reads:

https://www.meziantou.net/testing-an-asp-net-core-application-using-testserver.htm

https://docs.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/test-aspnet-core-services-web-apps

https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0

https://www.roundthecode.com/dotnet/asp-net-core-web-api/asp-net-core-testserver-xunit-test-web-api-endpoints

More info on the pipelines, by MSDN:

enter image description here

enter image description here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading