Пересчет и устранение зависимости Autofac в интеграционном тесте в AspNetCore с помощью TestServer - PullRequest
0 голосов
/ 09 января 2019

Я использую AspNetCore 2.2 Следующие (более) документы здесь: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2

Я использую Autofac, мой класс запуска имеет следующие методы:

public void ConfigureServices(IServiceCollection services)
public void ConfigureContainer(ContainerBuilder containerBuilder) //this is where things can be registered directly with autofac and runs after ConfigureServices
public void Configure(...) //the method called by runtime

То, как я использую Autofac, как рекомендовано в его документах, это Program.cs like this

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseKestrel()
            .ConfigureServices(services => services.AddAutofac())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .ConfigureAppConfiguration((builderContext, config) =>
            {
                var env = builderContext.HostingEnvironment;
                config
                    .AddJsonFile("appsettings.json", false, true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true)
                    .AddEnvironmentVariables();
            });
}

Сейчас я использую TestServer для моего тестового проекта, в котором я хочу использовать настоящий класс запуска. Но я бы хотел изменить одну из зависимостей.

Я видел, что существует метод, доступный от WebHostBuilder до .ConfigureTestServices(services => {});

поэтому я попробовал следующее:

public abstract class ComponentTestFeature
    : Feature
{
    protected HttpClient HttpClient { get; }

    protected ComponentTestFeature()
    {
        var configuration =
            new ConfigurationBuilder()
                .AddJsonFile("appsettings.Test.json")
                .Build();

        var webHostBuilder =
            new WebHostBuilder()
                .ConfigureServices(services => services.AddAutofac())
                .ConfigureTestServices(services =>
                {
                    services.AddScoped<IEventStoreManager, MockEventStoreManager>();
                })
                .UseConfiguration(configuration)
                .UseStartup<Startup>();

        var server = new TestServer(webHostBuilder);
        HttpClient = server.CreateClient();
        var myService = server.Host.Services.GetRequiredService<IEventStoreManager>();
    }
}

Как видите, я хочу использовать MockEventStoreManager реализацию для IEventStoreManager, чтобы эта реализация была разрешена контейнером. Однако это работает не так, как ожидалось, и в MyService решена оригинальная, а не фиктивная реализация.

Кто-нибудь знает, как я могу добиться того, чего хочу?

ОБНОВЛЕНИЕ 1: После дополнительных исследований мне пришлось создать проблему на github AspNetCore, потому что метод расширения выполняется до ConfigureContainer, поэтому я не могу переопределить зависимости autofac и не получить контейнер autofac позже. https://github.com/aspnet/AspNetCore/issues/6522

ОБНОВЛЕНИЕ 2: Просто к сведению, вот так выглядит Startup.cs. Как видите, все зависимости, кроме mvc, зарегистрированы в контейнере autofac.

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

// This is where things can be registered directly with autofac and runs after ConfigureServices, so it will override it
public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterType<EventStoreManager>().As<IEventStoreManager>();
}

и я хочу использовать MockEventStoreManager реализацию для IEventStoreManager в моих тестах, поэтому мне нужно переопределить (из моего тестового проекта), что регистрация Autofac хорошим способом.

Ответы [ 2 ]

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

Зарегистрируйте проверенную реализацию в конструкторе контейнеров для теста, используя ConfigureTestContainer

//...
.ConfigureServices(services => services.AddAutofac())
.ConfigureTestContainer<ContainerBuilder>(builder => {
    builder.RegisterType<MockEventStoreManager>().As<IEventStoreManager>();
})
//...

Это должно позволить избежать фактической реализации, которая добавляется Startup.ConfigureContainer как

Если более одного компонента предоставляют одну и ту же услугу, Autofac будет использовать последний зарегистрированный компонент в качестве поставщика по умолчанию для этой услуги :

Ссылка Регистрация по умолчанию

ConfigureTestContainer вызывается после Startup.ConfigureContainer, поэтому последняя регистрация в макете будет поставщиком услуг по умолчанию.

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

Есть несколько вариантов:

  • Создайте пользовательскую реализацию своей зависимости в своем тестовом сервере. проект

  • Реализация и ручная регистрация ложной реализации вашей зависимости с помощью слепка типа "Moq"

...