首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将SeedData注入自定义WebApplicationFactory的最佳方法

将SeedData注入自定义WebApplicationFactory的最佳方法
EN

Stack Overflow用户
提问于 2019-01-15 15:29:12
回答 2查看 1.2K关注 0票数 0

我在集成测试中剽窃了来自mightysoft docs站点的以下代码,并对其稍加修改以满足我的需求:

代码语言:javascript
复制
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}");
                }
            }
        });
    }
}

用于测试,如:

代码语言:javascript
复制
_client = new CustomWebApplicationFactory<Startup>(new SeedDataClass()).CreateClient();

这一切都是可行的,但我希望将泛型添加到定制的web应用程序工厂类中,并将这段代码移动到我正在进行内部测试工作的nuget包中。

就像这样:

代码语言:javascript
复制
public class CustomWebApplicationFactory<TStartup, TContext>
    : WebApplicationFactory<TStartup> 
    where TStartup : class 
    where TContext : DbContext

我被困在如何将SeedDataClass类实例提供/注入到我的新的通用自定义web应用程序工厂中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-15 15:54:50

这就是我要做的:

弹药厂:

代码语言:javascript
复制
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}");
                }
            }
        });
    }
}

已核实的用法:

代码语言:javascript
复制
    _client = new GenericWebApplicationFactory<Startup, GatewayContext, SeedDataClass>().CreateClient();

使用示例种子类:

代码语言:javascript
复制
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推入到helper lib/nuget包中,这些包可以在其他项目中重新使用。

票数 0
EN

Stack Overflow用户

发布于 2019-01-15 15:45:53

如果您只是试图使类似的构造函数适应您的CustomWebApplicationFactory<TStartup>类的前一个实现

代码语言:javascript
复制
_client = new CustomWebApplicationFactory<Startup>(new SeedDataClass()).CreateClient();

那么您的新构造函数将如下所示:

代码语言:javascript
复制
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;
    }
}

然后更新对构造函数的调用,如下

代码语言:javascript
复制
new CustomWebApplicationFactory<Startup, YourDbContext>(new SeedDataClass()).CreateClient();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54201951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档