作为实践测试驱动开发的新手,我经常陷入如何对数据库的持久性进行单元测试的困境。

我知道从技术上讲,这将是一个集成测试(而不是单元测试),但我想找出以下方面的最佳策略:

  1. 测试查询。
  2. 测试插入件。如果插入失败,我如何知道插入出错了?我可以通过插入然后查询来测试它,但是我怎么知道查询没有错误呢?
  3. 测试更新和删除——与测试插入相同

执行这些操作的最佳实践是什么?


关于测试SQL:我知道这是可以做到的,但是如果我使用像 NHibernate 这样的 O/R 映射器,它会在用于输出查询的别名中附加一些命名疣,因为这在某种程度上是不可预测的,我不确定我是否可以测试那。

我应该放弃一切并仅仅信任 NHibernate 吗?我不确定这是否谨慎。

有帮助吗?

解决方案

查看 DB 单元。它是一个 Java 库,但必须有一个 C# 等效库。它可以让您用一组数据准备数据库,以便您了解数据库中的内容,然后您可以与 DB Unit 交互以查看数据库中的内容。它可以针对许多数据库系统运行,因此您可以使用实际的数据库设置,或者使用其他东西,例如 Java 中的 HSQL(具有内存选项的 Java 数据库实现)。

如果您想测试您的代码是否正确使用数据库(您很可能应该这样做),那么这是隔离每个测试并确保数据库准备好预期数据的方法。

其他提示

作为 迈克·斯通说, DbUnit 非常适合在运行测试之前使数据库进入已知状态。测试完成后,DbUnit 可以将数据库恢复到运行测试之前的状态。

数据库单元 (Java)

数据库管理系统

您可以通过模拟数据库连接来进行单元测试。通过这种方式,您可以构建方法调用流程中的特定查询成功或失败的场景。我通常构建我的模拟期望,以便忽略实际的查询文本,因为我真的想测试该方法的容错能力以及它如何处理自身——SQL 的细节与此目的无关。

显然这意味着您的测试实际上不会验证该方法 作品, ,因为SQL可能是错误的。这就是集成测试发挥作用的地方。为此,我希望其他人会有更彻底的答案,因为我自己才刚刚开始掌握这些问题。

我在这里写了一篇关于 数据层的单元测试 这涵盖了这个确切的问题。对(可耻的)插件表示歉意,但文章太长,无法发布在这里。

我希望这对您有帮助 - 在过去 6 个月的 3 个活跃项目中,它对我来说非常有效。

问候,

罗布·G

我在对持久性进行单元测试时遇到的问题,特别是在没有 ORM 并因此模拟数据库(连接)的情况下,您并不真正知道查询是否成功。您的查询可能是专门为特定数据库版本设计的,并且只能在该版本上成功。如果你模拟你的数据库,你永远不会发现这一点。所以在我看来,单元测试的持久性作用有限。您应该始终添加针对目标数据库运行的测试。

为了 NHibernate, ,我绝对主张只是嘲笑 NHibernate API 对于单元测试——相信库会做正确的事情。如果您想确保数据确实进入数据库,请进行集成测试。

对于基于 JDBC 的项目,可以使用我的 Acolyte 框架: http://acolyte.eu.org 。它允许模拟您想要测试的数据访问,受益于 JDBC 抽象,而无需管理特定的测试数据库。

我还会模拟数据库,并检查查询是否符合您的预期。存在测试检查错误 sql 的风险,但这会在集成测试中检测到

从技术上讲,持久性单元测试不是单元测试,而是集成测试。

对于使用 mbUnit 的 C#,您只需使用 SqlRestoreInfo 和 RollBack 属性

    [TestFixture]
    [SqlRestoreInfo(<connectionsting>, <name>,<backupLocation>]
    public class Tests
    {

        [SetUp]
        public void Setup()
        {

        }

        [Test]
        [RollBack]
        public void TEST()
        {
           //test insert. 
        }
    }

在 NUnit 中也可以做同样的事情,只是属性名称略有不同。

至于检查查询是否成功,通常需要执行第二次查询,以查看数据库是否已按预期更改。

我通常创建一个存储库并使用它来保存我的实体,然后检索一个新的实体。然后我断言检索到的内容等于保存的内容。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top