ASP.NET Boilerplate,带有真实数据库的测试用例

时间:2017-07-03 02:57:49

标签: c# integration-testing aspnetboilerplate

我正在为ASP.NET 5.x的项目使用asp.net样板文件。我正在尝试为这个项目创建测试用例,它将调用现有的测试数据库(一个数据库用于主机,另一个数据库用于租户)。到目前为止我的步骤是:

  1. TestBase类构造函数中,我调用的方法与MultiTenantMigrateExecuter.Run()一样,它将为Test Host数据库和Test Tenant数据库播种数据(我将使用主机db和单个租户数据库进行测试)。播种将与真实数据库相同,只是测试数据库的名称不同。
  2. 同样来自TestBase类构造函数我从主机数据库获取TenantId。
  3. 接下来,我试图从租户数据库中获取任何种子用户 像这样:var user= UsingDbContext(context => context.Users.FirstOrDefault(t => t.UserName== "johndoe"));但当然这将调用HostDb而不是TenantDb。
  4. 我找到了一种方法来调用TenantDb,方法是将代码包装在这样的using语句中,避免context和usint存储库,以便能够从TenantDb获取我需要的用户:

    using (this.AbpSession.Use(tenant.Id, null))
    {
        // get the TenantDb.User here by using the User repository
    }
    

    ...然后在我写的每个测试用例中都这样:

    using (this.AbpSession.Use(AbpSession.TenantId, AbpSession.UserId))
    {
        // make calls to the Tenant database here by using Tenant repository
    }
    

    但这不是最干净的解决方案,它有其局限性。

    问题是:在我的情况下是否有更好的方法,在TestBase类中设置上下文以默认调用Tenant数据库而不是Host数据库?

    我也试过这个,但它没有用......

    protected T UsingTenantDbContext<T>(Func<TestAppDbContext, T> func)
    {
        T result;
    
        using (this.AbpSession.Use(AbpSession.TenantId, AbpSession.UserId))
        {
            using (var context = LocalIocManager.Resolve<TestAppDbContext>())
            {
                context.DisableAllFilters();
                result = func(context);
                context.SaveChanges();
            }
        }
    
        return result;
    }
    

1 个答案:

答案 0 :(得分:0)

用代码玩了一会后,我找到了问题的答案...... 在TestBase类中,我创建了一个新的静态属性:

internal static MyAppDbContext tenantContext;

静态,因为这个类会被多次继承,但是tenantContext只能设置一次。

接下来我创建了以下方法:

protected void CreateTenantDbContext()
{
    if (tenantContext == null)
    {
        using (var context = LocalIocManager.Resolve<MyAppDbContext>())
        {
            // AbpSession.TenantId is set in a previous method.
            // Usin the host context, get the Connection String for the necessary tenant
            var encryptedDbConnString = context.Tenants.FirstOrDefault(x => x.Id == AbpSession.TenantId)?.ConnectionString;

            // Decrypt the string
            var decryptedDbConnString = SimpleStringCipher.Instance.Decrypt(encryptedDbConnString);

            // Create the context for the tenant db and assign it to the static property tenantContext
            tenantContext = LocalIocManager.Resolve<MyAppDbContext>(new { nameOrConnectionString = decryptedDbConnString });
        }
    }
}

创建后,您可以在测试用例中使用它。