我在 .NET Core 中开发集成测试。因为 Controller 有多个依赖项,所以手动创建它们的实例很不方便。以下是我如何创建 ServiceProvider 实例以能够访问 .NET Core native DI 容器:
HostingEnvironment env = new HostingEnvironment();
env.ContentRootPath = Directory.GetCurrentDirectory();
env.EnvironmentName = "Development";
Startup startup = new Startup(env);
ServiceCollection sc = new ServiceCollection();
startup.ConfigureServices(sc);
ServiceProvider = sc.BuildServiceProvider();
Startup
类取自测试程序集。
令我惊讶的是,服务提供商无法创建 Controller 实例。它可以实例化已注册的服务,但不能实例化 Controller 。有人知道为什么会这样吗?
最佳答案
您应该使用 TestServer
,它会引导一个完整的测试环境(可选择使用不同的启动类或环境变量,您可以在其中将数据存储替换为内存存储)。
ASP.NET 核心 documentation很好地涵盖了这个案例。
var server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
// this would cause it to use StartupIntegrationTest or ConfigureServicesIntegrationTest / ConfigureIntegrationTest methods (if existing)
// rather than Startup, ConfigureServices and Configure
.UseEnvironment("IntegrationTest"));
在这些替代/环境相关的方法中,您可以将集成测试特定的替换/DI 配置。
其次,默认情况下, Controller (以及标签助手和 View 组件)未注册到 DI 系统。 Controller 工厂将解析类型。如果您希望通过内置或第三方 IoC 容器解析 Controller ,则必须告诉 ASP.NET Core 显式注册它们(请参阅 this related question)。
这是一个例子:
services
.AddMvc()
.AddControllersAsServices()
.AddViewComponentsAsServices()
.AddTagHelpersAsServices();
我建议您使用第一种方法,因为它更一致,并且正是存在具有环境支持的 Startup
类的原因。
更新
重要补充。如果您使用 TestServer
,您还可以访问其 DI 容器(IServiceProvider
实例)。
var server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
.UseEnvironment("IntegrationTest"));
var controller = server.Host.Services.GetService<MyController>();
关于dependency-injection - 为什么 ServiceProvider 无法在 ASP.NET Core 中创建 Controller 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42222919/