Внедрение зависимостей ASP.NET Core: передача аргументов во время выполнения - PullRequest
0 голосов
/ 15 февраля 2019

Я использую внедрение ядра ASP.NET в своем тестовом проекте , чтобы установить текстовый контекст, используемый в моих тестах (поэтому я не могу использовать здесь инъекцию конструктора).В ConfigureServices я регистрирую службы, которые работают нормально:

  public void ConfigureServices(IServiceCollection services)
  {
      // Scans assemblies and adds MediatR handlers, preprocessors, and postprocessors implementations to the container.            
      services.AddMediatR(
       typeof(Application.Logic.Queries.FindUserByEmailAddressHandler));            
      services.AddTransient<ILocalDb, LocalDb>(l => new LocalDb(null));
      services.AddTransient<IUnitOfWork, UnitOfWork>(uow => new UnitOfWork(""));            
      services.AddTransient<IUserRepository, UserRepository>();
  }

Однако при попытке получить экземпляр моей единицы работы у меня возникает проблема:

   var localDb = serviceProvider.GetService<ILocalDb>();
   var unitOfWork = serviceProvider.GetService<IUnitOfWork>(); <- need to pass constructor parameter

Вывидите, конструктор UnitOfWork принимает строку подключения, и мне нужно передать эту строку подключения, полученную из localDb (LocalDb создает тестовую базу данных на лету).

В StructureMap я мог бы передать параметр конструктору при получениинапример:

  x.For<IUnitOfWork>().Use<UnitOfWork>().Ctor<string>().Is(localDb.ConnectionString); });

Как я могу сделать это с помощью внедрения зависимостей ASP.NET Core?

Ответы [ 2 ]

0 голосов
/ 09 августа 2019

Нет необходимости передавать аргумент UnitOfWork, такой как выше.Определите свою структуру UnitOfWork в конфигурации, подобной этой

            var mySqlConn = Configuration.GetSection("MySqlConnection").Get<MySqlConnection>();
            services.AddDbContext<MySQLContext>(options => options.UseMySql(mySqlConn.MySqlConnectionString));

            services.AddScoped(typeof(IRepository<,>), typeof(Repository<,>));
            services.AddTransient(typeof(IUnitOfWork<>), typeof(UnitOfWork<>));

Visual Studio разрешит ее во время выполнения

0 голосов
/ 16 февраля 2019

Я нашел решение.

Я выполняю каждый тест в своем собственном текстовом контексте, например (упрощенный пример):

  using (var context = IntegrationTestEnvironment.Setup())
  {
      User bobbyUserDo = new User();
      Profile bobbyPatientDo = new Patient(bobbyUserDo, "bobbyPatient@hotmail.com");
      var bobbyUserDb = await context.UserRepository.AddOrUpdateAsync(bobbyUserDo);
      bobbyUserDb.Should().NotBeNull();
      bobbyUserDb.Id.Should().BeGreaterThan(0);
      bobbyUserDb.Profiles.Should().HaveCount(1);
      bobbyUserDb.Profiles.First().Id.Should().BeGreaterThan(0);
  }

В моем методе установки я подготавливаю среду:

  public static IntegrationTestContext Setup(bool prefillWithTestData)
  {           
        var webHost = WebHost.CreateDefaultBuilder()                
            .UseStartup<Startup>()
            .Build();
        var serviceProvider = new DependencyResolverHelpercs(webHost);
  }

Метод Startup содержит метод ConfigureServices, где я настраиваю все службы, которые мне нужны для теста:

  public void ConfigureServices(IServiceCollection services)
    {            
        // Scans assemblies and adds MediatR handlers, preprocessors, and postprocessors implementations to the container.            
        services.AddMediatR(typeof(Application.Logic.Queries.FindUserByEmailAddressHandler));

        var localDb = new LocalDb();
        services.AddSingleton<ILocalDb, LocalDb>(uow => localDb);
        services.AddSingleton<IUnitOfWork, UnitOfWork>(uow => new UnitOfWork(localDb.ConnectionString));
        services.AddSingleton<IUserRepository, UserRepository>();
    }

В то время я создаю LocalDb (который создает локальныйбазы данных), и после этого я могу просто передать строку подключения в мою единицу работы.

Тест может быть выполнен в контексте, где у меня правильно настроено внедрение зависимостей, и он действителен в этом тесте.Вот почему я использовал Singleton: экземпляры совпадают с контекстом этого конкретного теста;и после теста все удаляется и локальная база данных удаляется.

...