Custom appsettings.json File for ASP.NET Core Integration Tests

ASP.NET Core introduced the concept of TestServer for the integration testing of web applications. Integration tests need web applications to run with all the bells and whistles to make sure that all the components work together with no flaws. Often we need special settings for integration tests as web applications cannot use live services and the easiest way to do it is to use a special appsettings.json file. This blog post shows how to do it.

Getting Started

Let's start with minimalistic integration test from ASP.NET Core integration tests document.

public class HomeControllerTests : IClassFixture<WebApplicationFactory<Startup>>
{
    private readonly WebApplicationFactory<Startup> _factory;
 
    public HomeControllerTests(WebApplicationFactory<Startup> factory)
    {
        _factory = factory;
    }
 
    [Theory]
    [InlineData("/")]
    public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
    {
        // Arrange
        var client = _factory.CreateClient();
 
        // Act
        var response = await client.GetAsync(url);
 
        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString());
    }
}

This test verifies that all URLs given in the inline data end with a response code in a range from 200-299 and with a text/html content type. This test doesn't validate what the user is seeing on page. It just makes sure that the request doesn't fail. All the logic in the tested controller actions is tested by unit tests.

Adding a Custom appsettings.json File

Integration tests expect an environment with all external services needed by our application. As we don't run tests against live environment we have to set up a special set of services used by integration tests. We can run these tests on some continuous integration (CI) server or a service like Azure DevOps. With separate set of services comes the need for separate configuration files.

Add a new appsettings.json file to the integration tests project and make Visual Studio copy it to the output directory with every build.

For this example, I'm using SQL Server LocalDB and here's my appsettings.json file.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=MediaGalleryTests;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Note: Make sure you override all environment specific settings in the appsettings.json file used in the integration tests to make sure that references to live databases and services are not available for integration tests.

Including Custom appsettings.json

We have to tweak our test class to make it includes the correct appsettings.json. As TestServer is run in an output folder of the integration tests project, we just have to configure the web host and load appsettings.json from there.

public class HomeControllerTests : IClassFixture<WebApplicationFactory<Startup>>
{
    private readonly WebApplicationFactory<Startup> _factory;
 
    public HomeControllerTests(WebApplicationFactory<Startup> factory)
    {
        var projectDir = Directory.GetCurrentDirectory();
        var configPath = Path.Combine(projectDir, "appsettings.json");
 
        _factory = factory.WithWebHostBuilder(builder =>
        {
            builder.ConfigureAppConfiguration((context,conf) =>
            {
                conf.AddJsonFile(configPath);
            });
 
        });
     }
 
    [Theory]
    [InlineData("/")]
    public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
    {
        // Arrange
        var client = _factory.CreateClient();
 
        // Act
        var response = await client.GetAsync(url);
 
        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString());
    }
}

When I run the integration test above in debug mode and put a breakpoint from the Startup class to the line next to the connection string, I can see that the database context will use a connection string from appsettings.json in integration tests project.

Wrapping Up

The mechanism of ASP.NET Core integration tests makes it easy to tweak and extend web host used to run web applications with integration tests. As we use separate set of external services and databases with integration tests, we have to make web application use configuration file that overrides default settings. We added a custom appsettings.json file to the integration tests project and configured a web host builder to load this settings file when the web application is started for the tests. The only danger here is to remember that we need to override all the settings related to external databases and services as appsettings.json of web application is loaded before the one for integration tests.

 

 

 

 

Top