'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:

[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 1:[1]

It's because when you start the WebApi, and send a real request to it, behind the scenes it calls several methods in which it's validating your request, before it calls your controller action. In those methods it's setting the ModelState.IsValid property to false. On the other hand when you call your controller action directly from tests, nothing validates your request, hence your ModelState.IsValid is set to true by default.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 funatparties