Using custom appsettings.json with ASP.NET Core integration tests

ASP.NET Core introduced the concept of TestServer for integration testing of web applications. Integration tests need web application run with all bells and whistles to make sure that all components work together with no flaws. Often we need special settings for integration tests as web application cannot use live services and easiest way to do it is to use 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 URL-s given in inline data end with response code in range from 200-299 and with content type text/html. This test doesn’t validate what user is seeing on page. It just makes sure that request doesn’t fail. All logic in tested controller actions is tested by unit tests.

Adding custom appsettings.json

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

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

Copy integration tests appsettings.json always to output directory

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

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

NB! Before appsettings.json of integration tests project the one from web application is loaded. Make sure you override all environment specific settings in appsettings.json of 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 include correct appsettings.json. As TestServer is run in output folder of integration tests project we just have to configure 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 integration test above in debug mode and put breakpoint in Startup class to line next of connection string I can see that database context will use connection string from appsettings.json in integration tests project.

Connection string from integration tests appsettings.json

Wrapping up

The mechanism of ASP.NET Core integration tests makes it easy to tweak and extend web host used to run web application 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 custom appsettings.json to integration tests project and configured web host builder to load this settings file when web application is started for tests. The only danger here is to remember that we need to override all settings related to external databases and services as appsettings.json of web application is loaded before the one for integration tests.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    4 thoughts on “Using custom appsettings.json with ASP.NET Core integration tests

    Leave a Reply

    Your email address will not be published. Required fields are marked *