Лучший способ ввести SeedData в пользовательский WebApplicationFactory - PullRequest
0 голосов
/ 15 января 2019

Я выполнил плагиат приведенного ниже кода с сайта mightysoft docs при интеграционном тестировании и немного адаптировал его для своих нужд:

public class CustomWebApplicationFactory<TStartup>
    : WebApplicationFactory<TStartup> where TStartup : class
{
    private readonly SeedDataClass _seed;

    public CustomWebApplicationFactory(SeedDataClass seed)
    {
        _seed = seed;
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        base.ConfigureWebHost(builder);
        builder.UseEnvironment("Development");
        builder.ConfigureServices(services =>
        {
            var serviceProvider = new ServiceCollection()
                .AddEntityFrameworkInMemoryDatabase()
                .BuildServiceProvider();

            services.AddSingleton(_seed);

            services.AddDbContextPool<GatewayContext>(options =>
            {
                options.UseInMemoryDatabase("InMemoryDbForTesting");
                options.UseInternalServiceProvider(serviceProvider);
                options.EnableSensitiveDataLogging();
            });

            var sp = services.BuildServiceProvider();

            using (var scope = sp.CreateScope())
            {
                var scopedServices = scope.ServiceProvider;
                var db = scopedServices.GetRequiredService<GatewayContext>();
                var logger = scopedServices
                    .GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

                var seed = scopedServices.GetRequiredService<SeedDataClass>();

                db.Database.EnsureCreated();

                try
                {
                    seed.InitializeDbForTests(db);
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, $"An error occurred seeding the database with test messages. Error: {ex.Message}");
                }
            }
        });
    }
}

Для использования как в тесте, как:

_client = new CustomWebApplicationFactory<Startup>(new SeedDataClass()).CreateClient();

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

Примерно так:

public class CustomWebApplicationFactory<TStartup, TContext>
    : WebApplicationFactory<TStartup> 
    where TStartup : class 
    where TContext : DbContext

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

Ответы [ 2 ]

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

Вот куда я шел с этим:

исправленный завод:

public class GenericWebApplicationFactory<TStartup, TContext, TSeed>
    : WebApplicationFactory<TStartup>
    where TStartup : class
    where TContext : DbContext
    where TSeed : class, ISeedDataClass
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        base.ConfigureWebHost(builder);
        builder.UseEnvironment("Development");
        builder.ConfigureServices(services =>
        {
            var serviceProvider = new ServiceCollection()
                .AddEntityFrameworkInMemoryDatabase()
                .BuildServiceProvider();

            services.AddSingleton<ISeedDataClass,TSeed >();

            services.AddDbContextPool<TContext>(options =>
            {
                options.UseInMemoryDatabase("InMemoryDbForTesting");
                options.UseInternalServiceProvider(serviceProvider);
                options.EnableSensitiveDataLogging();
            });

            var sp = services.BuildServiceProvider();
            using (var scope = sp.CreateScope())
            {
                var scopedServices = scope.ServiceProvider;
                var db = scopedServices.GetRequiredService<TContext>();
                var logger = scopedServices.GetRequiredService<ILogger<GenericWebApplicationFactory<TStartup, TContext, TSeed>>>();

                var seeder = scopedServices.GetRequiredService<ISeedDataClass>();

                db.Database.EnsureCreated();

                try
                {
                    seeder.InitializeDbForTests();
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, $"An error occurred seeding the database with test messages. Error: {ex.Message}");
                }
            }
        });
    }
}

Исправлено использование:

    _client = new GenericWebApplicationFactory<Startup, GatewayContext, SeedDataClass>().CreateClient();

С примером класса семян:

public interface ISeedDataClass
{
    void InitializeDbForTests();
}

public class SeedDataClass : ISeedDataClass
{
    private readonly GatewayContext _db;

    public SeedDataClass(GatewayContext db)
    {
        _db = db;
    }

    public void InitializeDbForTests()
    {
        _db.Users.AddRange(
            // add some users here
        );

        _db.SaveChanges(true);
    }
}

Теперь я могу заполнить базу данных в памяти, как мне кажется, нужным для каждого проекта, где он используется, и теперь мой GenericWebApplicationFactory может быть помещен в вспомогательный пакет lib / nuget, который будет повторно использоваться в других проектах.

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

Если вы просто пытаетесь адаптировать похожий конструктор к прежней реализации вашего CustomWebApplicationFactory<TStartup> класса

_client = new CustomWebApplicationFactory<Startup>(new SeedDataClass()).CreateClient();

тогда ваш новый конструктор будет выглядеть так:

public class CustomWebApplicationFactory<TStartup, TContext> : WebApplicationFactory<TStartup> 
    where TStartup : class 
    where TContext : DbContext
{
    private readonly SeedDataClass _seed;

    public CustomWebApplicationFactory(SeedDataClass seed)
    {
        if (seed == null) throw new ArgumentNullException(nameof(seed));

        _seed = seed;
    }
}

, а затем обновите ваш вызов конструктора следующим образом:

new CustomWebApplicationFactory<Startup, YourDbContext>(new SeedDataClass()).CreateClient();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...