WebApplicationFactory 中的覆盖启动不映射端点
Override Startup in WebApplicationFactory does not map endpoints
我已经配置了一个 xUnit 项目来测试 Identity Server 的实现。我创建了一个 TestStartup
class 继承 Startup
并覆盖我的 Identity Server 实现以用于测试目的。问题是当我使用自定义 WebApplicationFactory
调用 TestStartup
时,我的端点未映射。如果我从我的自定义 WebApplicationFactory
调用 Startup
,我的端点被映射。
Startup.cs
protected readonly IConfiguration _configuration;
protected readonly IWebHostEnvironment _webHostEnvironment;
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
_configuration = configuration;
_webHostEnvironment = environment;
}
public virtual void ConfigureServices(IServiceCollection services)
{
///code goes here
ConfigureIdentityServices(services);
}
/// <summary>
/// Split into its own method so we can override for testing
/// </summary>
/// <param name="services"></param>
public virtual void ConfigureIdentityServices(IServiceCollection services)
{
///code goes here
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseRouting();
//app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
测试Startup.cs
public TestStartup(IConfiguration configuration, IWebHostEnvironment environment) : base(configuration, environment)
{
}
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
}
/// <summary>
/// In memory identity database implementation for testing
/// </summary>
/// <param name="services"></param>
public override void ConfigureIdentityServices(IServiceCollection services)
{
//test implementation
}
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
base.Configure(app, env);
}
自定义 WebApplicationFactory
public class ApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
protected override IWebHostBuilder CreateWebHostBuilder()
{
return WebHost.CreateDefaultBuilder(null).UseEnvironment("Development")
.UseStartup<TStartup>();
}
}
控制器测试Class
public class UserControllerTests : IClassFixture<ApplicationFactory<Startup>>
{
private readonly ApplicationFactory<Startup> _factory;
public UserControllerTests(ApplicationFactory<Startup> factory)
{
_factory = factory;
}
[Fact]
public async Task Get_Users()
{
var client = _factory.CreateClient();
var result = await client.GetAsync("/user/users");
result.StatusCode.Should().Be(HttpStatusCode.OK);
}
}
当我 运行 我的控制器测试时,如果注入 TestStartup
而不是 Startup
,我不会从端点路由返回任何端点,即使我调用 base.Configure(app,env)
方法来自我的 TestStartup
class.
我有完全相同的问题。在我的自定义 WebApplicationFactory 子类中使用子类启动导致没有端点被注册,而 UseStartup 注册它们。
奇怪的是我有另一个 API 项目(没有身份),其中使用子类启动实际上注册了端点。试图在启动时注释掉所有内容,但身份项目中的 services.AddControllers 和 app.UseRouting/app.UseEndpoints 除外,它仍然不起作用。
编辑:
找到了解决方案。显然 services.AddControllers 只在执行程序集中注册路由,在子类集成测试场景中是测试程序集。
通过添加所需的控制器作为应用程序部分,路由系统选择路由:
services.AddControllers()
.AddApplicationPart(typeof(<controllername>).Assembly);
事情会成功的。
我已经配置了一个 xUnit 项目来测试 Identity Server 的实现。我创建了一个 TestStartup
class 继承 Startup
并覆盖我的 Identity Server 实现以用于测试目的。问题是当我使用自定义 WebApplicationFactory
调用 TestStartup
时,我的端点未映射。如果我从我的自定义 WebApplicationFactory
调用 Startup
,我的端点被映射。
Startup.cs
protected readonly IConfiguration _configuration;
protected readonly IWebHostEnvironment _webHostEnvironment;
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
_configuration = configuration;
_webHostEnvironment = environment;
}
public virtual void ConfigureServices(IServiceCollection services)
{
///code goes here
ConfigureIdentityServices(services);
}
/// <summary>
/// Split into its own method so we can override for testing
/// </summary>
/// <param name="services"></param>
public virtual void ConfigureIdentityServices(IServiceCollection services)
{
///code goes here
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseRouting();
//app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
测试Startup.cs
public TestStartup(IConfiguration configuration, IWebHostEnvironment environment) : base(configuration, environment)
{
}
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
}
/// <summary>
/// In memory identity database implementation for testing
/// </summary>
/// <param name="services"></param>
public override void ConfigureIdentityServices(IServiceCollection services)
{
//test implementation
}
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
base.Configure(app, env);
}
自定义 WebApplicationFactory
public class ApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
protected override IWebHostBuilder CreateWebHostBuilder()
{
return WebHost.CreateDefaultBuilder(null).UseEnvironment("Development")
.UseStartup<TStartup>();
}
}
控制器测试Class
public class UserControllerTests : IClassFixture<ApplicationFactory<Startup>>
{
private readonly ApplicationFactory<Startup> _factory;
public UserControllerTests(ApplicationFactory<Startup> factory)
{
_factory = factory;
}
[Fact]
public async Task Get_Users()
{
var client = _factory.CreateClient();
var result = await client.GetAsync("/user/users");
result.StatusCode.Should().Be(HttpStatusCode.OK);
}
}
当我 运行 我的控制器测试时,如果注入 TestStartup
而不是 Startup
,我不会从端点路由返回任何端点,即使我调用 base.Configure(app,env)
方法来自我的 TestStartup
class.
我有完全相同的问题。在我的自定义 WebApplicationFactory 子类中使用子类启动导致没有端点被注册,而 UseStartup 注册它们。 奇怪的是我有另一个 API 项目(没有身份),其中使用子类启动实际上注册了端点。试图在启动时注释掉所有内容,但身份项目中的 services.AddControllers 和 app.UseRouting/app.UseEndpoints 除外,它仍然不起作用。
编辑: 找到了解决方案。显然 services.AddControllers 只在执行程序集中注册路由,在子类集成测试场景中是测试程序集。 通过添加所需的控制器作为应用程序部分,路由系统选择路由:
services.AddControllers()
.AddApplicationPart(typeof(<controllername>).Assembly);
事情会成功的。