为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
潇湘沐 2021-11-28 19:46:44
我在 asp.net core startup.cs 文件中有以下注册:    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的实现还是UserService。我尝试使用 ASP.NET Core 内置 IServiceCollection 直接在 Startup.ConfigureServices 方法中注册 UserService 并且它在调试时工作:services.AddSingleton<IUserService, UserService>();那么,当我使用 Autofac 作为 IoC 容器并且集成测试项目可以正常工作时,我该如何解决这个问题呢?
查看完整描述

3 回答

?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

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

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

  • WebHost 特定的 ConfigureServices

  • 启动类 ConfigureServices

  • 启动类 ConfigureContainer

在适当的位置添加 ConfigureTestServices 时,它看起来(虽然我还没有通过)它在 WebHost 和启动类 ConfigureServices 之后运行......但它仍然在 ConfigureContainer 之前运行。

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

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

  • 使用 Microsoft 注册语言而不是本机 Autofac,将您需要覆盖的注册移出ConfigureContainer和移入其中一种ConfigureServices方法。

  • 以其他方式执行覆盖,例如使用ASPNETCORE_ENVIRONMENT设置Test和提供ConfigureTestContainer方法。(特定于环境的注册方法示例在文档中。)


查看完整回答
反对 回复 2021-11-28
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

当像这样使用 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后执行,并会正确地覆盖IUserService有TestUsersService


查看完整回答
反对 回复 2021-11-28
?
holdtom

TA贡献1805条经验 获得超10个赞

对于来自 google 的那些,我想添加到 Michael 的出色答案中,该答案ConfigureTestContainer不适用于Microsoft从 .NET Core 3.0 开始通过网络主机推荐的通用主机。然而,Autofac 团队的 Alistair Evans 提出了一种解决方法。不幸的是,它依赖于IStartupConfigureContainerFilter可能会在 .NET 5.0 中删除的弃用。

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

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


查看完整回答
反对 回复 2021-11-28
  • 3 回答
  • 0 关注
  • 213 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信