ASP.Net 6自定义Web应用程序工厂引发异常

xqk2d5yq  于 2023-03-09  发布在  .NET
关注(0)|答案(3)|浏览(177)

我正在将现有的ASP.NET 5 Web应用程序迁移到ASP.NET 6,并遇到了通过集成测试的最后障碍。
我自定义了WebApplicationFactory,但它抛出了异常: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}");
                    }
                }
            });
        }
    }

例外情况:

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

任何建议和见解都将受到赞赏。

xytpbqjk

xytpbqjk1#

由于Program.cs中的这一行而发生错误:

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

我添加这个是因为我想保留args,所以我使用了WebApplication.CreateBuilder(args)。感谢@davidfowl,我使用了下面的代码片段:

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

并删除了出错的代码行。请注意,只要输入参数与默认值不同,builder.WebHost.UseContentRoot就会抛出异常。在我的示例中,只要运行集成测试,它就会抛出异常,但正常运行应用程序时不会。

7gcisfzg

7gcisfzg2#

当我尝试将API创建为窗口服务时,我遇到了同样的问题,
我用下面的代码解决了

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

yb3bgrhw3#

当我将API迁移到.NET6时,我在集成测试中遇到了同样的问题。
我通过在我的自定义WebApplicationFactory中添加builder.UseContentRoot(".")解决了这个问题。
完整代码:

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

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

相关问题