如何测试数据库相关的code。与NUnit的?

问题描述:

我想要编写单元测试与NUnit的击中了数据库。我想有数据库中为每个测试的一致状态。我以为交易将使我撤消每个测试,所以我四处搜查,发现几篇文章,从2004 - 05年度的话题:

I want to write unit tests with NUnit that hit the database. I'd like to have the database in a consistent state for each test. I thought transactions would allow me to "undo" each test so I searched around and found several articles from 2004-05 on the topic:

这些似乎解决各地实施NUnit的自定义属性它建立在回滚操作DB每次测试执行后的能力。

These seem to resolve around implementing a custom attribute for NUnit which builds in the ability to rollback DB operations after each test executes.

这是伟大的,但...

That's great but...


  1. 这是否在功能本身的NUnit存在的地方?

  2. 的这项技术已经在过去4年中加以改进?

  3. 这仍然是测试数据库相关的code的最佳方式?


编辑:这不是我想专门测试我DAL,它更是我想测试我的code片与数据库进行交互。对于这些测试是不接触和可重复的,这将会是真棒,如果我能每一个数据库后复位。

it's not that I want to test my DAL specifically, it's more that I want to test pieces of my code that interact with the database. For these tests to be "no-touch" and repeatable, it'd be awesome if I could reset the database after each one.

此外,我想缓和到具有此时没有测试代替已有的项目这一点。出于这个原因,我不能切实脚本从头开始一个数据库和数据为每个测试。

Further, I want to ease this into an existing project that has no testing place at the moment. For that reason, I can't practically script up a database and data from scratch for each test.

NUnit现在有一个[回滚]属性,但我preFER做不同的方式。我使用TransactionScope类。有一对夫妇的方式来使用它。

NUnit now has a [Rollback] attribute, but I prefer to do it a different way. I use the TransactionScope class. There are a couple of ways to use it.

[Test]
public void YourTest() 
{
    using (TransactionScope scope = new TransactionScope())
    {
        // your test code here
    }
}

既然你没有告诉TransactionScope的的承诺它会自动回滚。它的工作原理,即使断言失败或其他异常。

Since you didn't tell the TransactionScope to commit it will rollback automatically. It works even if an assertion fails or some other exception is thrown.

另一种方法是使用[设置]创建的TransactionScope和[TearDown中]调用Dispose就可以了。它减少了一些code重复,但完成同样的事情。

The other way is to use the [SetUp] to create the TransactionScope and [TearDown] to call Dispose on it. It cuts out some code duplication, but accomplishes the same thing.

[TestFixture]
public class YourFixture
{
    private TransactionScope scope;

    [SetUp]
    public void SetUp()
    {
        scope = new TransactionScope();
    }

    [TearDown]
    public void TearDown()
    {
        scope.Dispose();
    }


    [Test]
    public void YourTest() 
    {
        // your test code here
    }
}

这是作为一个单独的测试using语句作为安全的,因为NUnit的将保证TearDown中被调用。

This is as safe as the using statement in an individual test because NUnit will guarantee that TearDown is called.

说了这么多我不认为这击中了数据库测试是不是真的单元测试。我仍然写他们,但我认为他们是集成测试。我还看到他们提供的价值。一个地方,我经常使用它们在测试中的LINQ to SQL code。我不使用设计。我手写的DTO的和属性。我已经知道弄错了。集成测试帮助赶上我的错误。

Having said all that I do think that tests that hit the database are not really unit tests. I still write them, but I think of them as integration tests. I still see them as providing value. One place I use them often is in testing LINQ to SQL code. I don't use the designer. I hand write the DTO's and attributes. I've been known to get it wrong. The integration tests help catch my mistake.