Search code examples
c#unit-testingasp.net-coreasp.net-core-mvc-2.0

ASPNet.Core HostingEnvironment for Integration Tests?


In building the Integration tests for my ASPNet.Core web app, https://learn.microsoft.com/en-us/aspnet/core/testing/integration-testing, I am coming across an issue. The Startup is run when I run the app and the configuration is read and contains all the information in my apsettings.json file. Now, when I run the integration test as shown below. the Startup is run but the configuration is different. Why would that happen and how do I make sure it reads the one for the app itself?

[TestFixture]
class HSMControllerTests
{
    private readonly TestServer _server;
    private readonly HttpClient _client;

    public HSMControllerTests()
    {
        _server = new TestServer(new WebHostBuilder()
        .UseStartup<Startup>());
        _client = _server.CreateClient();
    }

    [Test]
    public async global::System.Threading.Tasks.Task GET_PingHSM_ShouldSucceedAsync()
    {
        HttpResponseMessage response = await _client.GetAsync("HSM/PingHSM");
        Assert.NotNull(response);
        Assert.IsInstanceOf<OkObjectResult>(response);
    }
}

I am getting the exception Missing configuration section ServiceConfig.

This is how the WebHost is built in Program.cs in my app:

WebHost.CreateDefaultBuilder(args)
       .UseStartup<Startup>()
       .UseKestrel(o => o.AddServerHeader = false)
       .Build();

Could the difference in how it is built in the Test code be the problem?

Modified ControllerTest constructor:

public HSMControllerTests()
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(Path.GetFullPath(@"../../../../HSM.WebApi.IntegrationTests"))
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();

    Configuration = builder.Build();

    _server = new TestServer(WebHost.CreateDefaultBuilder()
        .UseStartup<Startup>());
    _client = _server.CreateClient();
}

Now, how to inject the new Configuration into the Startup? Our Startup is defined like this:

public Startup(IConfiguration configuration, IHostingEnvironment environment)
        : base(typeof(Startup), configuration, environment)
{
}

modification based on last post by @poke

_server = new TestServer(WebHost.CreateDefaultBuilder()
    .ConfigureAppConfiguration(configBuilder => new ConfigurationBuilder()
        .SetBasePath(Path.GetFullPath(@"../../../../HSM.WebApi.IntegrationTests"))
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables()
    )
    .UseStartup<Startup>());

Got it working, somewhat...

var config = new ConfigurationBuilder()
    .SetBasePath(Path.GetFullPath(@"../../../../HSM.WebApi.IntegrationTests"))
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables();

var Configuration = config.Build();

_server = new TestServer(WebHost.CreateDefaultBuilder()
    .UseConfiguration(Configuration)
    .UseStartup<Startup>());
_client = _server.CreateClient();

But now, the HostingEnvironment is set to the directory of the Tests app vs. the directory of the Web app and it attempts to read to appsettings.json file from there in the HomeController constructor, here:

public HSMController(IHostingEnvironment hostingEnvironment)
{
    _hostingEnvironment = hostingEnvironment;
    contentRootPath = _hostingEnvironment.ContentRootPath;
}

Solution

  • Copy the appsettings.json file to the integration tests project folder and set it to Copy Always and it works correctly.