Как мне вставить поддельные в DI-контейнер? - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь внедрить подделки в DI-контейнер, и я ожидаю, что они будут использоваться вместо тех, которые указаны при запуске. Я попробовал это

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, он по-прежнему использует экземпляр, подключенный при запуске, а не тот, который был предоставлен с помощью метода ConfigureServices в тесте. Есть идеи, если это выполнимо?

1 Ответ

0 голосов
/ 08 января 2019

При использовании компоновщика веб-хоста с WebHostBuilder.ConfigureServices службы, настроенные на компоновщике, регистрируются в очень конкретное время, когда создается веб-хост. Однако ConfigureServices в вашем классе Startup называется после этого .

Таким образом, хотя вы можете использовать ConfigureServices на компоновщике для добавления сервисов на ваш веб-хостинг, Startup по-прежнему позволяет перезаписывать все. Обычно это хорошая вещь, но, конечно, она не поможет вам, когда вы захотите провести интеграционное тестирование своего приложения.

Я бы предложил вам использовать новый WebApplicationFactory для создания интеграционных тестов. Он уже поставляется с множеством утилит, которые помогут вам с вашими интеграционными тестами .

Одна из вещей, которую фабрика позволяет вам делать, - вводить фиктивные службы для тестирования . Для этого вы можете использовать ConfigureTestServices метод расширения в конструкторе веб-хоста.

Под капотами фабрика веб-приложений использует IStartupConfigureServicesFilter для этой работы. Вы можете зарегистрировать реализации этого в своем приложении, и их метод ConfigureServices будет запущен для настройки конвейера конфигурации службы для типа Startup. Таким образом, вы можете зарегистрировать несколько действий по настройке и запускать их явно в конце.

Так что если по какой-то причине вы не можете или не хотите использовать фабрику веб-приложений (хотя это значительно упрощает интеграционное тестирование), вы все равно можете сделать это в явном виде следующим образом:

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);
        };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...