如何在核心集成测试中覆盖来自其他容器 ASP.NET DI 注册



我在核心启动.cs文件中 asp.net 注册了以下内容:

public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<UserService>().As<IUserService>();
}

这是为了配置 Autofac 容器。我还有另一个集成测试项目,我有一个CustomWebApplicationFactory类,我正在尝试替换IUserService接口的实现。

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(services =>
{
services.AddSingleton<IUserService, TestUsersService>();
});
}

当我调试测试项目并且 IUserService 的实现仍然是用户服务时,它似乎不起作用。

我尝试使用内置 ASP.NET Core内置IServiceCollection直接在Startup.ConfigureServices方法中注册UserService,并在调试时工作:

services.AddSingleton<IUserService, UserService>();

那么,当我使用 Autofac 作为 IoC 容器并且集成测试项目将按预期正常工作时,如何解决问题?

您可能会遇到操作顺序问题。一般来说,最后获胜。这适用于Autofac和DI容器的基本Microsoft。

假设您已经通读了有关 Autofac ASP.NET Core 集成的文档,您将看到当ConfigureContainer到位时,操作顺序大致如下:

  • 特定于虚拟主机的配置服务
  • 启动类配置服务
  • 启动类配置容器

当添加配置测试服务时,它看起来像(虽然我还没有逐步完成(它在WebHost和启动类ConfigureServices之后运行...但它仍在配置容器之前运行。

这将很容易测试-创建具有三种不同实现的服务接口。在每个级别注册不同的实现。解析控制器中的接口。你得到了哪一个?那是最后一个跑的。现在从应用程序中删除该注册,然后重试。你得到的下一个是什么?这是倒数第二个。等等。

Autofac 采用预先构建的IServicesCollection并循环访问它,将其添加到本机 Autofac 容器中。一旦发生这种情况,是否修改集合就无关紧要了。Autofac 无法控制 ASP.NET Core 中启动机制的执行顺序;它只知道 ASP.NET 核心说:"这是要继续导入的最终服务集合!如果这没有在正确的阶段发生,您必须做以下两件事之一:

  • 将需要覆盖的注册从ConfigureContainer移动到ConfigureServices方法之一,使用 Microsoft 注册语言而不是本机 Autofac。
  • 以其他方式执行覆盖,例如使用TestASPNETCORE_ENVIRONMENT设置并提供ConfigureTestContainer方法。(文档中提供了特定于环境的注册方法的示例。

当像这样使用 ContainerBuilder 时:

public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<UserService>().As<IUserService>();
}

您必须使用 ConfigureTestContainer 而不是 ConfigureTestServices,如下所示:

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestContainer<ContainerBuilder>(containerBuilder =>
{
containerBuilder.RegisterType<TestUsersService>().As<IUserService>();
});
}

这是在调用 ConfigureContainer 之后执行的,并将正确覆盖IUserServiceTestUsersService

对于来自谷歌的那些,我想补充一下迈克尔的出色答案,即ConfigureTestContainer不适用于 .NET Core 3.0 Microsoft通过网络主机推荐的通用主机。然而,Autofac团队的Alistair Evans提出了一种解决方法。遗憾的是,它依赖于在 .NET 5.0 中可能会删除的已弃用IStartupConfigureContainerFilter

这意味着,目前在 .NET 5.0 中,使用通用主机时,无法模拟集成测试中外部 DI 容器注入的依赖项。

幸运的是,ASP.NET 团队的David Fowler正在调查这个问题。

最新更新