Search code examples
c#asp.netsql-serverasp.net-web-apiintegration-testing

Prevent SQL Server Connection in ASP.Net Integration test


I have a standard ASP.Net Web API Project with a DB setup that looks something like this:

Startup.cs

services.AddDbContext<ProjectDbContext>(opts =>
    opts.UseSqlServer(Configuration.GetConnectionString("ProjectDb")));

This works as intended.

I also have an integration test setup, where I attempt to replace the SQL Server connection with an In-Memory one, for a clean slate every test run:

ProjectWebApplicationFactory.cs

public class ProjectWebApplicationFactory : WebApplicationFactory<Startup> {
    protected override void ConfigureWebHost(IWebHostBuilder builder) {
        builder.ConfigureServices(services => {
            var prodDb = services.SingleOrDefault(s => s.ServiceType == typeof(ProjectDbContext));
            services.Remove(prodDb);
            services.AddDbContext<ProjectDbContext>(opts => {
                opts.UseInMemoryDatabase(Guid.NewGuid().ToString());
            });
    }
}

This again works correctly when running locally. However, when pushing this code to a build / test server it begins to fail. The initial SQL Server DB Context attempts to connect to a DB prior to getting replaced with the in memory version. Since the server is available locally, but not on the test server, this causes all integration tests to fail before even being able to run.

What is the proper way to prevent the SQL Server Context from attempting to connect while running an integration test?


Solution

  • The issue was a typo in ProjectWebApplicationFactory.cs

    This line:

    var prodDb = services.SingleOrDefault(s => s.ServiceType == typeof(ProjectDbContext));
    

    Should have been:

    var prodDb = services.SingleOrDefault(s => s.ServiceType == typeof(DbContextOptions<ProjectDbContext>));
    

    The SQL Sever DB was still being used when running the integration test. This caused it not to fail not on startup, but when endpoints were actually called.

    Also related, the in memory database should not be created with a random Guid string, but instead a static value, e.g.

    opts.UseInMemoryDatabase("ProjectDb");