繁体   English   中英

如何将假货注入DI容器中?

[英]How do I inject fake into DI container?

我正在尝试将伪造品注入DI容器中,并且我希望使用伪造品来代替Startup中指定的伪造品。 我试过了

var topicWriterFake = A.Fake<IServiceBusTopicWriter>();
A.CallTo(() => topicWriterFake.Write(A<string>.Ignored, A<string>.Ignored))
                    .Returns(Task.CompletedTask);

var webHostBuilder = WebHost.CreateDefaultBuilder().UseStartup<Startup>();   

webHostBuilder.ConfigureServices(sc => sc.AddScoped(p => topicWriterFake));

var serviceProvider = new DependencyResolver(_webHostBuilder.Build());

var sut = serviceProvider.GetService<IStripeService>();

IStripeService依赖于IServiceBusTopicWriter。 上面的代码解析IStripeService时,它仍使用在Startup中连接的实例,而不是通过测试中的ConfigureServices方法提供的实例。 有什么想法可行吗?

当将Web Host Builder与WebHostBuilder.ConfigureServices一起使用时,在构建Web Host的特定时间将注册在Builder上配置的服务。 但是, Startup类中的ConfigureServices那之后被调用。

因此,尽管可以在构建器上使用ConfigureServices将服务添加到Web主机,但是Startup仍然允许您覆盖所有内容。 这通常是一件好事,但是当您想对应用程序进行集成测试时,当然不会帮到您。

我建议您使用新的WebApplicationFactory编写集成测试。 它已经带有许多实用程序,可以帮助您进行集成测试

工厂允许您做的一件事就是注入模拟服务进行测试 您可以在Web主机构建器上使用ConfigureTestServices扩展方法

IStartupConfigureServicesFilter ,Web应用程序工厂使用IStartupConfigureServicesFilter来完成这项工作。 您可以在应用程序中注册其实现,它们的ConfigureServices方法将运行以为Startup类型设置服务配置管道。 因此,您可以注册多个配置操作,并在最后显式运行它们。

因此,如果由于某种原因您不能或不想使用Web应用程序工厂(尽管这使集成测试容易得多),您仍然可以像下面这样明确地使这项工作:

var webHostBuilder = WebHost.CreateDefaultBuilder()
    .UseStartup<Startup>()
    .ConfigureServices(services =>
    {
        services.AddSingleton<IStartupConfigureServicesFilter>(new MockInjectorFilter(s =>
        {
            s.AddScoped(p => topicWriterFake);
        });
    });
public class MockInjectorFilter : IStartupConfigureServicesFilter
{
    private readonly Action<IServiceCollection> _configureServices;

    public ConfigureTestServicesStartupConfigureServicesFilter(Action<IServiceCollection> configureServices)
        => _configureServices = configureServices ?? throw new ArgumentNullException(nameof(configureServices));

    public Action<IServiceCollection> ConfigureServices(Action<IServiceCollection> next)
        => serviceCollection =>
        {
            next(serviceCollection);
            _configureServices(serviceCollection);
        };
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM