【问题标题】:Strategies for Using Mock Objects when Unit Testing DAOs单元测试 DAO 时使用 Mock 对象的策略
【发布时间】:2010-09-28 15:04:22
【问题描述】:

我很好奇人们发现了哪些策略来对不涉及为每个测试方法加载(并且可能是卸载)真实数据库的数据访问类进行单元测试?您是否使用模拟对象来表示数据库连接?如果是这样,您是否需要将模拟对象传递给每个被测方法,从而强制 API 需要一个真正的数据库连接作为每个方法的参数?或者,您是在 setup() 中将模拟对象传递给构造函数吗?

我有一个类正在实现我认为是数据映射器(或者可能是网关)模式。它是负责封装 SQL 并返回(或保存)“业务对象”的类。其余代码可以与这个映射层和业务对象交互,完全不考虑持久性模型。此代码需要拥有/维护或只知道真实系统中的实时数据库连接。在测试中模拟这个是很棘手的。

问题是如何对这些映射器类之一进行单元测试。我最常看到的在 xUnit 下创建单元测试的做法是使用测试的 setup() 方法来实例化 SUT(被测系统),通常是您正在测试的对象,并将其存储在本地测试类中的变量。然后,您的每个测试方法都与该 SUT 的唯一实例进行交互。

但假设是,您在 setup() 方法中所做的任何事情都可能会复制到您的真实代码中的某个位置。因此,您必须将设置过程视为“每次我需要在现实世界中使用此对象时,我都希望重复重现此内容”。如果我在设置中将一个数据库连接传递给映射器的构造函数,那很好,但这是否意味着每次我想真正使用一个时,我都必须将一个实时数据库连接传递给映射器对象的构造函数?想象一下,您将有各种各样的地方需要检索或存储业务对象,并且要使用数据映射器对象,您每次都需要传入 db 连接?

就我而言,我正在尝试为这些数据映射器对象建立测试,以实现以下目标:

  1. 不需要实例化数据库连接对象并将其传递给映射器类的每个方法。
  2. 不要求测试用例连接到真实数据库或为每个测试方法动态创建真实但“测试”的数据库。

我基本上看到了两个建议,将连接对象作为参数传递(我已经解决过)或扩展 SUT 类仅用于测试并覆盖您在现实世界中使用的任何数据库连接设置过程以使用模拟代替系统。

我很好奇是否有其他人使用任何语言面临这些问题,以及您为解决这些问题做了什么?也许我缺少一些明显的东西?

【问题讨论】:

    标签: unit-testing testing tdd mocking


    【解决方案1】:

    根据我的经验,连接到数据库的责任是数据访问的痛点。我通过让 DAO 根据配置文件(app.config 等)来解决这个问题。这样我在编写测试时就不必担心这一点。 DAL 保留一个或多个数据库连接配置文件并在每次数据访问时连接/断开连接,因为最终连接池将负责物理连接/断开连接。

    对我有帮助的另一件事是在运行测试之前使用 dbUnit 加载基线数据。我发现直接进入数据库而不是使用模拟对象更容易。此外,通过连接到一个真实的数据库,我可以(在某种程度上)通过在不同线程中发出命令来测试并发性——模拟对象不会给我真正的行为。

    【讨论】:

      【解决方案2】:

      您可以使用 DbUnit 来测试 SQL

      【讨论】:

        【解决方案3】:

        这取决于您真正想要测试的内容。如果您想测试您的 SQL 是否符合您的预期,那就真的要进入 集成测试 领域了。假设您使用的是 Java,那么您可以使用几个纯 Java RDBMS 解决方案(Apache Derby、HSQLDB、H2)。

        另一方面,如果您真的只是在测试您的 Java JDBC 代码(即从 ResultSets 读取),那么您可以模拟 JDBC 的几乎所有相关部分,因为它们'主要是接口。 JMock 非常适合这个。只需将 setConnection() 方法添加到您的待测类,然后传入模拟的 java.sql.Connection 即可。这对于保持测试简短而有效。

        【讨论】:

          【解决方案4】:

          根据您的数据库设置的复杂程度,使用内存存储可能是一个不错的选择。

          我通常使用内存中的 SQLite 会话进行单元测试。这是内存中 100% 的完整数据库,无需文件,无需配置。就一行。

          现在这并不总是一种选择。 SQLite 不支持成熟的服务器数据库的所有 sql 功能。通常我会使用一个层来使我的代码数据库独立。在这些情况下,我只需切换到内存中的数据库实例,我会在每次设置/拆卸期间在内存中快速创建/销毁。

          您是否使用任何中间层来访问您的数据库?在大多数情况下,使用这种中间件的最大好处不是数据库可移植性,而是简化的测试工具。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-02-04
            • 2012-05-14
            • 2015-10-07
            • 1970-01-01
            相关资源
            最近更新 更多