11

I am migrating my existing ASP.Net 5 web app to ASP.Net 6 and bump into the final hurdles of getting the integration tests to pass.

I customize WebApplicationFactory and it throws exception: Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.

    public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "IntegrationTests");
            builder.ConfigureServices(services => {
                // Create a new service provider.
                var serviceProvider = new ServiceCollection()
                    .AddEntityFrameworkInMemoryDatabase().AddLogging()
                    .BuildServiceProvider();

                // Add a database context (AppDbContext) using an in-memory database for testing.
                services.AddDbContextPool<AppDbContext>(options =>
                {
                    options.UseInMemoryDatabase("InMemoryAppDb");
                    options.UseInternalServiceProvider(serviceProvider);
                    options.EnableSensitiveDataLogging();
                    options.EnableDetailedErrors();
                    options.LogTo(Console.WriteLine);
                });

                services.AddDbContextPool<AppIdentityDbContext>(options =>
                {
                    options.UseInMemoryDatabase("InMemoryIdentityDb");
                    options.UseInternalServiceProvider(serviceProvider);
                    options.EnableSensitiveDataLogging();
                    options.EnableDetailedErrors();
                    options.LogTo(Console.WriteLine);
                });
                services.AddScoped<SignInManager<AppUser>>();
                services.AddScoped<ILogger<UserRepository>>(provider => {
                    ILoggerFactory loggerFactory = provider.GetRequiredService<ILoggerFactory>();
                    return loggerFactory.CreateLogger<UserRepository>();
                });
                services.AddDistributedMemoryCache();
                // Build the service provider.
                var sp = services.BuildServiceProvider();

                // Create a scope to obtain a reference to the database contexts
                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var appDb = scopedServices.GetRequiredService<AppDbContext>();
                    var identityDb = scopedServices.GetRequiredService<AppIdentityDbContext>();
                    var logger = scopedServices.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

                    // Ensure the database is created.
                    appDb.Database.EnsureCreated();
                    identityDb.Database.EnsureCreated();

                    try
                    {
                        // Seed the database with test data.
                        SeedData.PopulateTestData(identityDb);
                        SeedData.PopulateTestData(appDb);
                    }
                    catch (Exception ex)
                    {
                        logger.LogError(ex, $"An error occurred seeding the " +
                            $"database with test messages. Error: {ex.Message}");
                    }
                }
            });
        }
    }

Exception:

  Message: 
    System.NotSupportedException : The content root changed from "C:\Projects\C#\AspNetCoreApi\src\Web.Api\" to "C:\Projects\C#\AspNetCoreApi\test\Web.Api.IntegrationTests\bin\Debug\net6.0\". Changing the host configuration using WebApplicationBuilder.WebHost is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.

  Stack Trace: 
    ConfigureWebHostBuilder.UseSetting(String key, String value)
    HostingAbstractionsWebHostBuilderExtensions.UseContentRoot(IWebHostBuilder hostBuilder, String contentRoot)
    Program.<Main>$(String[] args) line 58
    --- End of stack trace from previous location ---
    HostingListener.CreateHost()
    <>c__DisplayClass8_0.<ResolveHostFactory>b__0(String[] args)
    DeferredHostBuilder.Build()
    WebApplicationFactory`1.CreateHost(IHostBuilder builder)
    WebApplicationFactory`1.ConfigureHostBuilder(IHostBuilder hostBuilder)
    WebApplicationFactory`1.EnsureServer()
    WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
    WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers)
    WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
    WebApplicationFactory`1.CreateClient()
    MyControllerIntegrationTests.ctor(CustomWebApplicationFactory`1 factory) line 15

Any advice and insight is appreciated.

4
  • I have the same problem. The way I solved it, was by using Host.CreateDefaultBuilder(args) which works, but isn't the response the error message gives. Commented Nov 10, 2021 at 13:08
  • 1
    The error message explains what you need to do :) Commented Nov 11, 2021 at 18:06
  • 1
    Why doesn't this exception happen when running the application proper but only during integration test? Why is there such different behaviour? Commented Nov 12, 2021 at 1:38
  • I was having this same problem, but what made it so hard to figure out is it was presenting itself as a error 1053 when I would start my windows service. Event Viewer was useless. Finally I put my own logging in Program.cs to capture the problem and got the same error as described. I have been fighting with this for a while. I'm glad I am not alone on this. I was only experiencing this outside of Visual Studio when trying to run it as a windows service. This problem didn't even happen when you ran the EXE directly! This is goofy. Commented Aug 1, 2022 at 1:20

3 Answers 3

12

The error happens due to this line in Program.cs:

builder.WebHost.UseContentRoot(Path.GetFullPath(Directory.GetCurrentDirectory())); // Changing the host configuration using WebApplicationBuilder.Host is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.

I added this as I want to preserve args and therefore I used WebApplication.CreateBuilder(args). Thanks to @davidfowl I used the following code snippet instead:

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    ApplicationName = typeof(Program).Assembly.FullName,
    ContentRootPath = Path.GetFullPath(Directory.GetCurrentDirectory()),
    WebRootPath = "wwwroot",
    Args = args
});

and removed the faulting line of code. Note that builder.WebHost.UseContentRoot will throw exception whenever the input parameter differs from the default value. In my case, it throws exception whenever running the integration tests but NOT when running the application proper.

Sign up to request clarification or add additional context in comments.

1 Comment

This solved another issue for me, where when I deployed my .NET 6 app to Azure Web App, I would get a DirectoryNotFoundException (it looked at the D drive for some reason I still don't understand). So thanks a lot for giving a solution to that headache
8

I have came across the same issue when I tried to create .NET6 api as window service,

I solved with the below code

  var builder = WebApplication.CreateBuilder(new WebApplicationOptions
      {
        Args = args,
        ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
      });

Comments

1

I have the same issue in my integration test, when I have migrated the API to .NET6.

I solved this just by adding builder.UseContentRoot(".") in my customWebApplicationFactory.

The whole code :

public class CustomWebApplicationFactoryWithMock<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseContentRoot(".");

        builder.ConfigureServices(services =>
        {
            services.AddScoped<TService, TImpementation>();
        });
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.