Reputation: 195
In an ASPNET Core project I am trying to create some unit tests that would verify my data validation logic works fine.
My controller is very simple:
[HttpPost]
[Route("Track")]
public void Track([FromBody] DataItem item)
{
if (!ModelState.IsValid) throw new ArgumentException("Bad request");
_dataItemSaver.SaveData(item);
}
I am using a test base class that would set up the _myController
object as the controller under test.
public ControllerTestBase()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"buildversion.json", optional: true)
.AddEnvironmentVariables();
_config = builder.Build();
var services = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.AddDbContext<MyDbContext>(options =>
{
options.UseInMemoryDatabase();
})
.AddScoped<IDataItemSaver, DataItemSQLStorageService>()
.AddScoped<MyController>()
.Configure<MyConfig>(_config.GetSection(nameof(MyConfig)));
services
.AddMvc(mvcOptions =>
{
mvcOptions.Filters.AddService(typeof(GlobalExceptionFilter), 0);
});
_additionalDISetupActions?.Invoke(services);
_serviceProvider = services.BuildServiceProvider();
_myController = _serviceProvider.GetService<MyController>();
}
The test again is very simple:
[TestMethod]
public void Prop3Required()
{
// Arrange
var dataItem = new DataItem()
{
Prop1 = "Prop1",
Prop2 = "Prop2"
};
// Act & Assert
Assert.ThrowsException<ArgumentException>(() => _myController.Track(dataItem));
}
I am finding though that ModelState.IsValid
is true
when running a unittest even when my DataItem
is missing required attributes (Prop3
in this example). When testing the controller through the web with the same input, the validation works correctly (returning false
for ModelState.IsValid
).
How do I properly trigger the ASPNET Core logic for modelstate validation from a unit test?
Upvotes: 18
Views: 13498
Reputation: 1110
If you want to do a pure unit test you need to manually simulate the model state error because the model state validation is only triggered during runtime.
_myController.ModelState.AddModelError("yourItemFieldHere", "Your validation type here");
See https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/testing for more detail
Upvotes: 20
Reputation: 750
You should take a look at Integration Testing with ASP.NET Core (https://learn.microsoft.com/en-us/aspnet/core/testing/integration-testing), it is a very simple way to host your application in a test context and test your entire pipeline.
As explained in the documentation you could do something like this in your test method:
_server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
_client = _server.CreateClient();
// Pass a not valid model
var response = await _client.PostAsJsonAsync("Track", new DataItem());
Assert.IsFalse(response.IsSuccessStatusCode);
Upvotes: 25