Integration Testing With In-Memory Entity Framework

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

Integration Tests in Asp.Net

StackOverfow Question relating to adding DbContext to an integration test

Testing anAsp.Net web-app Using Integration Tests

Manually adding a DbContext for an integration test

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.