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?
You should take a look at Integration Testing with ASP.NET Core (https://docs.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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With