As part of a project that I’m working on, I’ve been playing around with integration tests. In this post, I’m going to combine this previous post to cover a full end-to-end test that creates and tests an in-memory representation of the database.
As a quick caveat, there are some concerns over these type of in-memory database versions: for complex databases, that may well be true, but this is a very simple example. However, you may find that if you do try to apply this to something more complex that it doesn’t work as you’d expect.
Let’s start with setting up the WebApplicationFactory:
var appFactory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(host =>
{
host.ConfigureServices(services =>
{
var descriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbContextOptions<MyDbContext>));
services.Remove(descriptor);
services.AddDbContext<MyDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryDB");
});
});
});
var httpClient = appFactory.CreateClient();
What we’re basically doing here is replacing the existing DB Context, with our in memory version. Next, we’ll prepare the payload:
var myViewModel = new myViewModel()
{
MyValue = new Models.NewValue()
{
Name = "test",
Uri = "www.test.com",
Description = "description"
}
};
var json = JsonSerializer.Serialize(myViewModel);
var content = new StringContent(
json,
System.Text.Encoding.UTF8,
"application/json");
Finally, we can call the endpoint:
// Act
using var response = await httpClient.PostAsync(
"/home/myendpoint", content);
In order to interrogate the context, we need to get the service scope:
var scope = appFactory.Services.GetService<IServiceScopeFactory>()!.CreateScope();
var dbContext = scope.ServiceProvider.GetService<MyDbContext>();
Assert.NotNull(dbContext);
Assert.Single(dbContext!.NewValues);
That should be all that you need. In addition to the caveats above, it’s not lightning fast either.
References
StackOverfow Question relating to adding DbContext to an integration test