集成测试中的自定义WebApplicationFactory未在Startup.cs(ASP.NET Core 3.1)



我遇到了一个问题,我使用的是自定义WebApplicationFactory,而它没有在我的Startup.cs中注册服务。我正在使用Asp.Net core 3.1和Xuit。

我在我的API(startup.cs(中使用扩展方法注册了以下内容:

public void ConfigureServices(IServiceCollection services)
{
services.AddBaseApiConfiguration(Configuration);
services.AddRepositoryServices();
services.AddApiServices();
services.AddMediatrServices();
}

根据MS文件:

SUT的数据库上下文在其Startup.ConfigureServices方法。测试应用程序的建设者ConfigureServices回调在应用的Startup.ConfigureServices代码已执行。

但上述情况并未发生。我使用的启动时的任何服务都没有被注册(,即我拥有的4个扩展方法从未被调用,也从未被注册(。这导致了一些问题:我的DB上下文在其构造函数中使用IMediatr,以便在上下文中发布事件。SaveChangesAsync(((成功时(。但由于我的服务从未注册,它找不到它。我如何确保这一点正确进行?

下面是我的定制工厂:

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder
.UseEnvironment("Development")
.ConfigureServices(services =>
{
// Remove the app's db context registrations
var descriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbContextOptions<AppDbContext>));

if (descriptor != null)
{
services.Remove(descriptor );
}
services.AddSingleton<IDbConnectionFactoryService, SqliteConnectionFactoryService>();
// Add a database context using an in-memory 
// database for testing.
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlite("Data Source=sqlitedemo.db");
});
// Build the service provider.
var sp = services.BuildServiceProvider();
// Create a scope to obtain a reference to the database context 
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<AppDbContext>();
// Ensure the database is created.
db .Database.EnsureDeleted();
db .Database.EnsureCreated();
}
});
}

编辑:Startup.cs中的服务似乎是在CustomWebApplication工厂服务之后调用的。这完全是奇怪的,根据.Net核心3.0,顺序被更改为相反。那么,为什么这种情况仍在发生呢?

编辑2:需要使用ConfigureTestServices而不是ConfigureServices。

我在文档中没有发现这一点,但调用ConfigureTestServices可以确保在调用启动服务后调用CustomWebApplicationFactory服务。根据文档,这一点没有被正确指出,但至少这可能会帮助其他遇到同样问题的人。

如果您只有几个带有常见模拟服务注册的集成测试,那么ConfigureTestServices工作得很好,但当许多测试需要自己的特定模拟注册时,它就不能很好地扩展。ConfigureTestServices要求您为每种情况重新构建主机及其DI容器。我开发了一个对MicrosoftDependencyInjection的扩展,它允许在不重建容器的情况下进行本地mock。查看-Rsi.DependencyInjection.

最新更新