ASP.Net 6 自定义 WebApplicationFactory 抛出异常
ASP.Net 6 custom WebApplicationFactory throws exception
我正在将我现有的 ASP.Net 5 网络应用程序迁移到 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
欢迎任何建议和见解。
由于 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
就会抛出异常。就我而言,它会在 运行 集成测试时抛出异常,但不会在 运行 应用程序正常时抛出异常。
我在尝试创建 .NET6 api 作为 window 服务时遇到了同样的问题,
我用下面的代码解决了
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
});
我正在将我现有的 ASP.Net 5 网络应用程序迁移到 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
欢迎任何建议和见解。
由于 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
就会抛出异常。就我而言,它会在 运行 集成测试时抛出异常,但不会在 运行 应用程序正常时抛出异常。
我在尝试创建 .NET6 api 作为 window 服务时遇到了同样的问题,
我用下面的代码解决了
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
});