问题描述
我正在努力使用ASP.NET Core 3.1应用程序中的SimpleInjector(4.9)在DI中设置DI,以进行集成测试,以便可以根据标准ASP依赖交换出已在Startup类中注册的目标配置服务. .NET Core启动配置.
I'm struggling with setting up DI using SimpleInjector (4.9) in my ASP.NET Core 3.1 application for my Integration Tests, so that I can dependency swap out target configured services that are registered in the Startup class as per standard ASP.NET Core startup configuration.
我想要实现的基本上是这样的:
What I want to achieve is basically something like this:
- 使用Microsoft.AspNetCore.TestHost.TestServer(或等效版本)托管"测试
- 将启动初始化为普通"状态,因此无需维护单独的IoC来进行测试和运行时
- 通过模拟交换/覆盖键依赖性,例如对外部服务和RabbitMQ的API调用
- 使用带有模拟功能的启动配置运行测试
我的问题是,我似乎找不到与SI容器进行交互的方法以使其覆盖依赖项,类似于亚当·斯托(Adam Storr)解决了.我试图从Adam Storr,Andrew Lock,Gunnar Peipman和当然的官方文档中发布的指南中汲取灵感,但是无论我如何尝试将解决方案与SimpleInjector结合使用,总会有一些不起作用的关键问题.
My problem is that I can't seem to find a way to interact with the SI Container to have it override the dependencies, similar to how Adam Storr solved it. I've tried to gather inspiration from the guides posted by Adam Storr, Andrew Lock, Gunnar Peipman, and of course the official docs, but no matter how I try and combine the solutions with SimpleInjector there's always something critical that doesn't work.
由于Startup是由.UseStartup生成的,因此我无法访问在Startup中创建的Container并更改其依赖关系,即使那样,这也意味着以某种复杂的方式公开Startup类.由于不再受支持.
I can't access the Container created within Startup and have it change the dependencies, since Startup is generated by .UseStartup, and even then it would mean exposing the Startup class in some convoluted way. I also can't inject a Container into Startup since that's not supported anymore.
但是,如果我尝试创建Startup的子类并使用它,则会导致默认情况下找不到Controllers的问题,因此Http(Test)Client返回404.而且,如果我尝试根据 Gunnar Peipman的建议,SimpleInjector失败, a:
But if I try to create a subclass of Startup and use that I end up with the issue that the Controllers can't be found by default and so the Http(Test)Client returns 404's. And if I try to resolve this as per Gunnar Peipman's suggestion SimpleInjector fails with a:
System.InvalidOperationException : For the SimpleInjectorControllerActivator to function properly, it requires all controllers to be registered explicitly in Simple Injector, but a registration for WeatherForecastController is missing. To ensure all controllers are registered properly, call the RegisterMvcControllers extension method on the Container from within your Startup.Configure method while supplying the IApplicationBuilder instance, e.g. "this.container.RegisterMvcControllers(app);"
(解决该问题的方法甚至不是最新的方法,因为不赞成使用RegisterMvcControllers(app)而是使用AddControllerActivation-参考)
(Which isn't even an up-to-date way to solve it since RegisterMvcControllers(app) is deprecated in favor of AddControllerActivation - ref)
我已经在此处上传了一个示例存储库,其中显示了问题;一些指导将不胜感激.
I've uploaded a sample repo here that shows the issue(s); some guidance here would be greatly appreciated.
推荐答案
进一步挖掘之后,我发现了阻止我进行所有尝试的问题:为了使集成测试注册控制器,您必须更改测试项目SDK来自:
After further digging, I found the issue that prevented all my attempts at working: In order to have your integration test register the controllers you have to change the test project SDK from:
<Project Sdk="Microsoft.NET.Sdk">
收件人:
<Project Sdk="Microsoft.NET.Sdk.Web">
很公平,它在先决条件,但老实说,我认为测试项目模板未附带已配置的模板,或者没有针对该模板的特定模板就不足为奇了这种(非常常见的)场景,或者我发现的所有指南都没有提到这一关键的配置.如果您信任模板,就很容易错过.
And fair enough, it does say so under the prerequisites, but to be honest I think it's beyond strange that the test project templates don't come with this already configured, or that there isn't a specific template for this - very common - scenario, or that none of the guides I've found mention this critical piece of configuration. It's very easy to miss if you trust in the templates.
修复此问题后,现在可以很简单地使用Startup的子类,并使用SimpleInjector进行模拟覆盖.
With this fixed, it's now quite simple to use a subclass of Startup with mocked overrides using SimpleInjector.
这篇关于如何在ASP.NET Core 3.1中使用简单注入器进行依赖项交换以进行集成测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!