我正在使用自定义WebApplication工厂
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup: class {
protected override void ConfigureWebHost(IWebHostBuilder builder) {
builder.ConfigureServices(services => {
// Create a new service provider.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
services.AddDbContext<GrabGoContext>(options => {
options.UseInMemoryDatabase("GrabGoDb");
options.UseInternalServiceProvider(serviceProvider);
});
services.AddSingleton<TestEmailServer>();
services.AddScoped<IEmailProvider, TestEmailProvider>(); // <- HERE
});
base.ConfigureWebHost(builder);
}
我想将名为IEmailProvider
的默认DefaultEmailProvider
服务切换到特殊的TestEmailProvider
,但是问题是方法ConfigureWebHost
在Startup.ConfigureServices(IServiceCollection services)
之前执行,因此我的服务DefaultEmailProvider
设置在TestEmailProvider
之后。因此,在我的ClientController
服务中,DeafultEmailProvider
代替了测试服务。
我的问题是:
如何使用WebApplicationFactory与DefaultEmailProvider
切换服务TestEmailProvider
?
@更新
好的,我已经更深入了。我发现方法builder.ConfigureTestServices()
覆盖了其他服务。但是,当在我的ConfigureWebHost(IWebHostBuilder builder)
方法中进行切换时,我尝试使用CreateClient()
创建新的HttpClient,它会抛出:
System.InvalidOperationException: 'A ConfigureServices method that returns an IServiceProvider is not compatible with the use of one or more IStartupConfigureServicesFilter. Use a void returning ConfigureServices method instead or a ConfigureContainer method.'
@更新28.05.2019
仍在寻找更好的解决方案,但我设法做了一些 hack 。
在我的Startup.cs
中,我交换了
services.AddScoped<IEmailProvider, SendGridEmailProvider>();
使用TryAdd [功能]
services.TryAddScoped<IEmailProvider, SendGridEmailProvider>();
答案 0 :(得分:1)
您可以根据环境进行操作。这只是将您指向正确方向的代码。
public IHostingEnvironment HostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
if (HostingEnvironment.IsDevelopment())
{
services.AddTransient<ITestService, TestService>();
}
else
{
services.AddTransient<IRealService, RealService>();
}
// other services
}
我希望这会有所帮助。
答案 1 :(得分:1)
我花了几个小时尝试做类似的事情(在集成测试中覆盖了服务)。原来ConfigureServices
在SUT(被测对象)服务配置之前 运行。 ConfigureTestServices
,但是,在之后运行,并且是您在其中覆盖模拟内容的地方。
尽管对此我确实确实发现了以下内容,但文档并不清楚:
答案 2 :(得分:1)
您应该能够在ConfigureWebHost中执行以下操作:
for-loop
您可能想使它更容易使用,只是像上面那样实现工厂,而不是使它通用。我还为您的内存数据库添加了略有不同的代码。
它还没有被编译,但是语法应该相距不远。 希望有帮助。