如何使用 NUnit 测试与数据库相关的代码? [英] How do I test database-related code with NUnit?

查看:15
本文介绍了如何使用 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 实现自定义属性的问题,该属性构建了在每次测试执行后回滚数据库操作的能力.

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

这很好,但是...

  1. 此功能是否存在于 NUnit 中的某个地方?
  2. 这项技术在过去 4 年中是否有所改进?
  3. 这仍然是测试数据库相关代码的最佳方式吗?

<小时>

我并不是想专门测试我的 DAL,而是我想测试与数据库交互的代码片段.为了让这些测试无接触"且可重复,如果我能在每次测试后重置数据库,那就太棒了.


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 现在有一个 [Rollback] 属性,但我更喜欢用不同的方式来实现.我使用 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.

另一种方法是使用 [SetUp] 创建 TransactionScope 和 [TearDown] 对其调用 Dispose.它减少了一些代码重复,但完成了同样的事情.

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 代码.我不使用设计器.我手写了 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.

这篇关于如何使用 NUnit 测试与数据库相关的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆