代码之家  ›  专栏  ›  技术社区  ›  Jon Limjap

如何对持久性进行单元测试?

  •  44
  • Jon Limjap  · 技术社区  · 17 年前

    作为一个实践测试驱动开发的新手,我经常在如何将测试持久性单元化到数据库这一问题上陷入困境。

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

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

    做这些的最佳实践是什么?


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

    我应该放弃一切,只相信NHibernate吗?我不确定这是否明智。

    10 回复  |  直到 17 年前
        1
  •  16
  •   Mike Stone    17 年前

    查看数据库单元。它是一个Java库,但是必须有一个C等价物。它允许您用一组数据准备数据库,以便知道数据库中有什么,然后您可以与数据库单元交互,以查看数据库中有什么。它可以运行在许多数据库系统上,因此您可以使用您的实际数据库设置,或者使用其他东西,如Java中的HSQL(具有内存中的Java数据库实现)。

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

        2
  •  15
  •   Community CDub    8 年前

    AS Mike Stone said ,dbunit非常适合在运行测试之前使数据库进入已知状态。测试完成后,dbunit可以将数据库恢复到运行测试之前的状态。

    DbUnit (Java)

    DbUnit.NET

        3
  •  4
  •   Rytmis    17 年前

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

    很明显,这意味着你的测试不会真正验证方法 作品 ,因为SQL可能是错误的。这就是集成测试开始的地方。为此,我希望其他人能有一个更彻底的答案,因为我刚刚开始和那些人打交道。

        4
  •  3
  •   OJ.    13 年前

    我在这里写了一篇关于 unit testing the data layer 它涵盖了这个确切的问题。为(可耻的)插头道歉,但文章太长了,无法在这里发表。

    我希望这对你有帮助-在过去的6个月里,我在3个积极的项目上工作得很好。

    当做,

    罗布G

        5
  •  2
  •   dlinsin JaviAlgaba    17 年前

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

        6
  •  2
  •   N00b Pr0grammer TChia    7 年前

    为了 NHibernate 我绝对赞成嘲笑 NHibernate API 对于单元测试——相信库会做正确的事情。如果您想要确保数据实际上被传递到数据库,那么就进行集成测试。

        7
  •  2
  •   cchantep    6 年前

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

        8
  •  1
  •   David Sykes    17 年前

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

        9
  •  1
  •   Dan TheCodeJunkie    17 年前

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

    使用c使用mbUnit,只需使用sqlRestoreInfo和rollback属性

        [TestFixture]
        [SqlRestoreInfo(<connectionsting>, <name>,<backupLocation>]
        public class Tests
        {
    
            [SetUp]
            public void Setup()
            {
    
            }
    
            [Test]
            [RollBack]
            public void TEST()
            {
               //test insert. 
            }
        }
    

    同样可以在nunit中完成,excpet属性名差别很小。

    至于检查您的查询是否成功,通常需要使用第二个查询来跟踪它,以查看数据库是否如您所期望的那样发生了更改。

        10
  •  1
  •   Thomas Eyde    16 年前

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