1

在研究 EF 和 Code First 时,我刚才问了一个问题(参考这个线程),关于如何防止测试相互重叠。我想为数据库播种,并且对每个测试类都这样做(使用 MSTest):

  public class CustomerSmokeTests {
    private const string CONNECTION_STRING = "server=localhost;database=CPT_CustomerDataSync_SmokeTests;uid=sa;pwd=Password1!;";

    private DatabaseFactory _dbfactory;
    private CustomerCacheContext _customerContext;

    [TestInitialize]
    public void Setup() {
      // set initializer to create new DB
      Database.SetInitializer(new SmokeTestCreateDbWithDataIfNotExists());
      Database.SetInitializer(new SmokeTestDropCreateDbWithDataAlways());

      // create new DB connection to local SQL Server
      _dbfactory = new DatabaseFactory(CONNECTION_STRING);

      // connect to DB to auto generate it
      _customerContext = _dbfactory.GetDataContext();
    }

    [TestCleanup]
    public void Cleanup() {
      _customerContext.Dispose();
      _dbfactory.Dispose();
    }

    // tests
}

然而,这里的问题是每个测试都会创建/破坏数据库(不理想,因为它们相互重叠并失败......如果你单独运行测试,它们都会按需要通过......而且这会大大减慢测试速度)。

一个好的解决方案是将它们包装在 TransactionalScopes 中,但是我想确保在测试运行开始时,使用种子信息重新生成数据库(因为种子在我的开发人员开发的测试中发生变化)。

一种蛮力的方法是在测试初始化​​中创建某种处理程序,它将检查数据库是否是最近创建的,如果没有,则使用种子信息创建它。如果不是,它将忽略该步骤。然后它会创建一个 TransactionalScope() 将在测试清理中回滚。

但是有没有更好的方法来处理这个问题?用这种蛮力方法获得过度设计的感觉......想法?

4

2 回答 2

2

Marvel 的回应让我朝着正确的方向思考……让它发挥作用,在这里解释有点长,所以我在这里写了博客:http ://www.andrewconnell.com/blog/archive/2012/05/02/isolating -integration-tests-with-ef4-x-code-first-amp-mstest.aspx

于 2012-05-02T10:07:32.873 回答
-1

通常,这些测试与每次检查都与持续集成服务器高度集成。因此,我认为如果您可以将 dbCreation 测试作为测试设置中的第一个测试,会更好,因为它会创建具有所有必要映射的 db。之后,在第一次测试时创建它,其他测试可以在您的基础 TestFixture 类中使用 Transactionscope 来满足您现在使用它的方式,并且您的集成测试可以有效地工作,因为您没有使用 TestInitialize 和 TestCleanup 创建数据库。

public class BaseTestFixture
{

TransactionScope transactionScope;

    [TestInitialize]
    public void InitializeTests()
    {            

        if (IsTransactionScopeNeeded)
        {
            transactionScope = new TransactionScope();
        } 
    }

    [TestCleanup]
    public void CleanUp()
    {
        if (transactionScope != null)
            transactionScope.Dispose();

    }

}

public class DbContextTests : BaseTestFixture
{

    protected override bool IsTransactionScopeNeeded
    {
        get
        {
            return false;
        }
    }

    //This test should run first 
    [TestMethod]
    public void CreateDatabase_DatabaseNotExistedOrObselete_DatabaseCreated()
    {
    }
}
于 2012-05-01T06:35:11.643 回答