为查询数据库的方法编写单元测试

本文关键字:单元测试 方法 查询 数据库 | 更新日期: 2023-09-27 18:21:28

我正在学习TDD,目前我有一种方法正在运行,但我想我应该尝试使用TDD重建它。

该方法本质上接受6个参数,查询数据库,执行一些逻辑并返回List<T>

我最初的测试包括检查空/零定义的字符串和int方法参数值,但现在我不知道该怎么办。如果我没有使用TDD,我只会创建代码来找到DB连接字符串并打开DB连接,查询数据库,读取值等。

很明显,我们在单元测试中无法做到这一点,所以我在寻求一些关于如何继续的建议。

为查询数据库的方法编写单元测试

请记住,TDD与其说是测试,不如说是良好的设计。这种方法太多了;这违反了"关注点分离"原则。

您已经确定了几个需要测试的领域:

该方法本质上接受6个参数,查询数据库,执行一些逻辑并返回List<T>

您有几个离散的步骤,代码中可能还有更多隐藏的步骤。当涉及到TDD时,打破这些是游戏的名称。

对于初学者来说,考虑执行逻辑的部分可能是个好主意。

您的方法是动态构建查询吗?把这部分也分解出来,并对其进行测试,以确保查询写得正确。

您可以将查询的执行放在一个独立的存储库或类似的存储库中,并据此编写集成测试。这样,您只需要一个简单的测试来访问数据库,而不是当前复杂的方法。

如果你试着按原样测试,你很可能会得到一个需要大量设置并复制所有业务逻辑的怪物测试,当它崩溃时,就不清楚出了什么问题。

一般来说,使用TDD测试数据库代码并没有什么"错误"。但是,您可以尝试抽象出数据库代码,然后对其进行模拟。

该方法本质上接受6个参数,查询数据库一些逻辑并返回一个列表

这似乎是太多了,不能成为一个单元可测试的代码!!

一个单元可测试代码应该做一些非常具体的事情,并在小模块中进行。所以,在您的情况下,您需要重构并将方法分解为以下部分(至少):

  • 数据库查询:封装在具有支持接口的DataProvider中。您的单元测试会模拟这个接口
  • 做一些逻辑:这是单元测试的最佳候选者。这应该是一个只接受数据提供者接口并执行逻辑并返回修改后的列表的模块,您将在单元测试中验证该列表

此外,请记住,单元测试应该至少涵盖每个可测试模块的三个场景:

  • 阳性检测
  • 阴性测试
  • 测试为无效值抛出有意义的异常

希望这会有所帮助。

另一个选项是在测试之前启动事务,然后进行回滚。通过这种方式,测试是独立的,因此根据一些定义,仍然可以被视为单元测试。

与其他答案中提到的相反,您应该在测试通过后重构代码以获得更好的设计。然后,您可以通过重新运行测试来验证您的重构没有破坏任何东西。

您可能需要尝试查看DbUnit,以便在数据访问层上运行单元测试。它使数据库在测试运行之间处于已知状态,防止测试数据库损坏。

您可以:

  1. 使用类/test-init来引发一个空白数据库或一个具有已知数据集的小型数据库的副本
  2. 在测试方法中输入测试数据(如果DB为空),然后执行查询,然后将结果与预期结果进行比较
  3. 在测试/类清理中删除DB

这将测试您的单元,但被一些人视为"集成测试"。-由于"单元"一词的歧义,"单元测试"一词有一些分歧。

您还可以使用内存中的DB或进程中的DB来简化测试环境。