'Turn `ReloadOnChange` off in config source for WebApplicationFactory

This is both a question and an answer. I've fixed my problem, but it seems a bit wrong.

My original problem is running my asp.net core integration tests in a bitbucket pipeline causes System.IO.IOException: The configured user limit (128) on the number of inotify instances has been reached. Some solutions call for changing some setting through sysctl, but that is restricted by bitbucket, so that isn't an option for me.

The second way of fixing this, as noted in these stackoverflow answers, is to turn reloadOnChange off.

My new problem is now, how do we best do this for the test WebApplicationFactory?

One solution that has worked for me, which is the least amount of code, seems like a total hack. I iterate through all the JsonConfigurationSource and set ReloadOnChange to false.

Full solution:

public class TestApplicationFactory : WebApplicationFactory<Startup>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureAppConfiguration(config =>
        {
            foreach (var source in config.Sources)
            {
                if (source is JsonConfigurationSource)
                {
                    var jsonConfigSource = (JsonConfigurationSource) source;
                    jsonConfigSource.ReloadOnChange = false;
                }
            }
        });
    }
}

Another solution, that I haven't tried, may be to override CreateWebHostBuilder(). However, it seems like more code and a lot of copy and paste from the default one.

Am I missing something? Is there a better way to do this?



Solution 1:[1]

Just experienced this issue myself running integration tests within a Linux container and followed the previous suggestions to switch off the ReloadOnChange within the WebApplicationFactory. Unfortunately that did not resolve the problem and integration tests were still failing with the same error:

System.IO.IOException: The configured user limit (128) on the number of inotify instances has been reached.

I also tried to configure xUnit to run the integration tests sequentially rather than in parallel, but that did not work either.

The solution that did work for me was to set the appropriate environment variable within the container that runs the integration tests:

export ASPNETCORE_hostBuilder__reloadConfigOnChange=false

Solution 2:[2]

builder.ConfigureAppConfiguration is there to configure your (main) application.

You can use builder.ConfigureHostConfiguration (see docs) to explicitly configure files to be read for the host.

builder.ConfigureHostConfiguration((hostingContext, config) =>
{
    config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false);
});

The host configuration is loaded. ASP.NET Core from 3.0 is built based on Generic host (rather than the Web Host of the former versions).

Solution 3:[3]

You can do this without inheriting from WebApplicationFactory by using the WithWebHostBuilder and ConfigureAppConfiguration extension methods:

var webAppFactory = new WebApplicationFactory<Startup>().WithWebHostBuilder(webHostBuilder =>
{
    webHostBuilder.ConfigureAppConfiguration((hostingContext, configBuilder) =>
        configBuilder.Sources.Where(s => s is FileConfigurationSource).ToList()
            .ForEach(s => ((FileConfigurationSource)s).ReloadOnChange = false));
});

This accomplishes the same thing as your original idea (which helped me a lot!), but more compact and without the need for a separate class definition.

Solution 4:[4]

I just encountered the same issue.

Setting the env variable DOTNET_hostBuilder:reloadConfigOnChange to false fixed it.

This solution works for net6 when you use the Generic Host. For other hosts, maybe try replacing DOTNET_ prefix with ASPNETCORE_

To make it simple, I set it in my code before creating the WebApplicationFactory

Environment.SetEnvironmentVariable("DOTNET_hostBuilder:reloadConfigOnChange", "false");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ben Wesson
Solution 2 Tseng
Solution 3 321_contact
Solution 4 sroll