Asp.net core 如何在ASP.NET Core 3.1中为集成测试使用简单注入器进行依赖项交换

Asp.net core 如何在ASP.NET Core 3.1中为集成测试使用简单注入器进行依赖项交换,asp.net-core,dependency-injection,asp.net-core-mvc,integration-testing,simple-injector,Asp.net Core,Dependency Injection,Asp.net Core Mvc,Integration Testing,Simple Injector,我正在努力在ASP.NET Core 3.1应用程序中为集成测试使用SimpleInjector(4.9)设置DI,以便根据标准ASP.NET Core启动配置替换在启动类中注册的目标配置服务 我想实现的基本目标是: 使用Microsoft.AspNetCore.TestHost.TestServer(或等效工具)来“主持”测试 将启动初始化为“正常”,因此无需为测试和运行时维护单独的IOC 使用模拟(如对外部服务和RabbitMQ的API调用)交换/覆盖密钥依赖关系 使用带模拟的启动配置运行测

我正在努力在ASP.NET Core 3.1应用程序中为集成测试使用SimpleInjector(4.9)设置DI,以便根据标准ASP.NET Core启动配置替换在启动类中注册的目标配置服务

我想实现的基本目标是:

  • 使用Microsoft.AspNetCore.TestHost.TestServer(或等效工具)来“主持”测试
  • 将启动初始化为“正常”,因此无需为测试和运行时维护单独的IOC
  • 使用模拟(如对外部服务和RabbitMQ的API调用)交换/覆盖密钥依赖关系
  • 使用带模拟的启动配置运行测试
  • 我的问题是,我似乎找不到一种与SI容器交互的方法,让它覆盖依赖项,类似于这样。我试图从亚当·斯托尔、安德鲁·洛克、甘纳·佩普曼(Gunnar Peipman)发布的指南中获得灵感,当然还有官方文档,但无论我如何尝试将解决方案与SimpleInjector结合起来,总会有一些关键的东西不起作用

    我无法访问在Startup中创建的容器并让它更改依赖项,因为Startup是由.UseStartup生成的,即使这样,也意味着以某种复杂的方式公开Startup类。我也无法将容器注入启动,因为

    但是如果我尝试创建Startup的子类并使用它,我最终会遇到一个问题,即默认情况下无法找到控制器,因此Http(测试)客户机返回404。如果我尝试按照SimpleInjector解决此问题,失败的原因是:

    System.InvalidOperationException:为了使SimpleInjectorControllerActivator正常工作,需要在Simple Injector中显式注册所有控制器,但缺少WeatherForecastController的注册。要确保所有控制器都已正确注册,请从启动中调用容器上的RegisterMvcControllers扩展方法。在提供IApplicationBuilder实例时配置方法,例如“this.Container.RegisterMvcControllers(app);”

    (这甚至不是解决此问题的最新方法,因为RegisterMvcControllers(应用程序)被弃用,取而代之的是AddControllerActivation-)


    我上传了一份样本回购协议,其中显示了问题;在此提供一些指导将不胜感激。

    在进一步挖掘之后,我发现了阻止我所有工作尝试的问题:为了让您的集成测试注册控制器,您必须将测试项目SDK更改为:

    <Project Sdk="Microsoft.NET.Sdk">
    
    
    
    致:

    
    
    公平地说,它确实在下面这样说,但老实说,我认为测试项目模板没有配置好,或者没有一个特定的模板用于这个非常常见的场景,或者我发现的指南中没有提到这个关键的配置部分,这是非常奇怪的。如果您信任模板,那么很容易错过


    修复了这个问题后,现在使用SimpleInjector使用模拟覆盖的Startup子类非常简单。

    进一步挖掘后,我发现了一个问题,它阻止了我所有的工作尝试:为了让集成测试注册控制器,您必须将测试项目SDK从以下位置更改:

    <Project Sdk="Microsoft.NET.Sdk">
    
    
    
    致:

    
    
    公平地说,它确实在下面这样说,但老实说,我认为测试项目模板没有配置好,或者没有一个特定的模板用于这个非常常见的场景,或者我发现的指南中没有提到这个关键的配置部分,这是非常奇怪的。如果您信任模板,那么很容易错过


    有了这个修复,现在使用SimpleInjector使用带有模拟覆盖的Startup子类就非常简单了。

    将Startup初始化为“正常”是什么意思,因此不需要为测试和运行时维护单独的IOC?您看过文档部分了吗?这有帮助吗?顺便说一句,感谢您在异常消息中用
    RegisterMvcControllers
    报告此问题。我是为此而创建的,它将在下一个版本中修复。@Steven我的意思是,我看到一些人建议维护一个完全独立的启动副本,该副本具有您想要的更改,就像“MockStartup”,只是每次对启动进行更改时,您都必须在MockStartup中进行相同的相对更改。我非常希望避免这种情况,正如我以前所看到的那样,副本会随着时间的推移而损坏。@Steven我已经查看了覆盖部分,如果你看到我的回购协议,你可以看到我只是用它来覆盖依赖项,但我的问题是我没有地方放置这个不在Startup.cs内的覆盖,这意味着它将包含测试逻辑。我的难题仍然是如何让我的测试使用Startup.cs,并在不将启动暴露于测试逻辑的情况下进行覆盖。什么是“将启动初始化为“正常”,因此不需要为测试和运行时维护单独的IOC”?您看过文档部分了吗?这有帮助吗?顺便说一句,感谢您在异常消息中用
    RegisterMvcControllers
    报告此问题。我是为此而创建的,它将在下一个版本中修复。@Steven我的意思是,我看到一些人建议维护一个完全独立的启动副本,该副本具有您想要的更改,就像“MockStartup”,只是每次对启动进行更改时,您都必须在MockStartup中进行相同的相对更改。我非常希望避免这种情况,因为我以前已经看到复制副本会随着时间的推移而损坏。@Steven我已经查看了覆盖部分,如果您看到我的回购,您可以看到我只是使用它来覆盖依赖项,但我的问题是我没有地方放置此覆盖