我使用
WebApplicationFactory
设置了一些集成测试,但在覆盖 ConfigureTestServices
方法中的某些服务时遇到了问题。
这是我的
WebApplicationFactory
:
public class TestWebApplicationFactory: WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(s =>
{
// Here I would like to access IConfiguration
var configuration = ....?
//and then use some values from configuration, while overriding others with some fixed test values
services.ConfigureMyService(new MyOptions
{
Option1 = config.Option1,
Option2 = "new-fixed-value",
... other options
});
});
}
}
这是我的生产启动:
public static class StartupExtensions
{
public static void ConfigureServices(
this IServiceCollection services,
IConfiguration configuration,
IWebHostEnvironment environment)
{
var config = configuration.Get<MyConfig>();
services.AddSingleton(config);
services.ConfigureMyService(new MyOptions
{
Option1 = config.Option1,
Option2 = config.Option2,
... other options
});
}
}
public class MyOptions
{
public string Option1{ get; set; }
public string Option2{ get; set; }
}
我尝试覆盖的服务已添加到我无权访问的外部包中的 DI 中。
MyService
可见性是内部的,因此不能直接从WebApplicationFactory
引用/覆盖它。覆盖它的唯一方法是再次调用 ConfigureMyService
方法:
// Defined in an external package I don't have access to. MyService visibility is Internal, so it cannot be referenced/overridden
private static void ConfigureMyService(this IServiceCollection services, MyOptions options)
{
var someService = new MyService(options.Option1, options.Option2);
services.AddSingleton<MyService>(someService);
}
我想我可以在
ConfigureTestServices
内部构建服务提供者并通过它获得 MyOptions
(s.BuildServiceProvider().GetRequiredService<MyOptions >()
),但这绝对是一种气味,我想避免这种情况。
您应该使用工厂方法延迟配置依赖项,而不是直接为其提供实例:
builder.ConfigureTestServices(services =>
{
services.AddSingleton<IAmazonDynamoDB>(serviceProvider =>
{
var configuration = serviceProvider.GetRequiredService<MyOptions>();
// Do your customization...
return MyFakeDynamoClient(configuration);
});
});