【问题标题】:Is there anything wrong with testing SQL with JUnit tests over JDBC?通过 JDBC 使用 JUnit 测试来测试 SQL 有什么问题吗?
【发布时间】:2014-09-02 07:23:26
【问题描述】:

我有一个 Java 应用程序,它使用准备好的语句对 PostgreSQL 数据库进行一些 JDBC 查询。查询不是很复杂,主要是一个衬垫,但无论如何我想对它们进行一些单元测试。

最初我编写了一个 JUnit 测试用例,它连接一个单独的测试数据库(当然不是生产数据库),在启动时擦除它,创建简单的测试内容并触发查询。我因这种方法而受到批评,因为“数据库不应该用于测试”。

“数据库用于测试”的原因是数据库引擎是我正在测试的代码(SQL)的解释器。在没有数据库的情况下测试 SQL 的要求听起来像是在没有 Java 虚拟机的情况下测试 Java 代码的要求。

由于哲学原因,某些代码永远不能被测试的说法听起来有些奇怪,这与实际上不应该使用大多数 SQL 功能(如范围或更复杂的查询或连接)的建议相同。我还在所有数据库活动周围使用了一个包装器类,并有一个不与数据库对话的“SQL 服务模拟”,并在各种其他测试中使用它,但我还需要测试这个模拟的实际生产实现。

是否有其他更好的方法来测试我的 JDBC 查询集,或者我只是没有做错什么?

【问题讨论】:

  • 对于 jdbc 测试,最好使用具有 Postgre 类似语法的内存或基于文件的数据库。也许,hsql 或 derby。
  • 当然,如果在测试中使用它比 Postgres 本身需要更少的努力。
  • 初始设置所需的工作 - 必须将额外的 hsql 库添加到类路径。但是修改后,构建将不再依赖外部服务器,这是一种很好的做法。

标签: java sql unit-testing testing


【解决方案1】:

Martin Fowler 有一篇关于单元测试中的外部依赖的好文章:

“即使是像我这样的经典测试人员在出现尴尬的协作时也会使用测试替身。在与远程服务交谈时,它们对于消除不确定性非常宝贵。事实上,一些经典的 xunit 测试人员还认为,任何与外部资源的协作,例如数据库或文件系统,应该使用双精度。部分原因是不确定性风险,部分原因是速度。 http://martinfowler.com/bliki/UnitTest.html

就个人而言,我认为如果您的测试设置它们的上下文而不是依赖于可能并不总是可用的外部系统,那会很好。

【讨论】:

    【解决方案2】:

    我在这篇博文中概述了我在单元测试中避免使用数据库的原因:http://blog.pdark.de/2008/07/26/testing-with-databases/

    总结一下:你在测试什么? PostgreSQL?为什么?他们不是已经有数千个单元测试来确保数据库按预期工作吗?

    为什么要测试 PostgreSQL?您应该测试您的代码。你不这样做的原因是那种唠叨的感觉“我可能会错过一些东西”。这种感觉的根源是你不知道自己在做什么。本能的本能是淹没大量代码中的焦虑(好像在单元测试中执行更多代码会使它变得更好)。

    解决方案:尝试将创建 SQL 查询的代码与实际执行它的代码分开。这样,您可以轻松拆分单元测试和集成测试。单元测试只是检查您的代码是否生成了正确的 SQL(只需调用“创建 SQL 查询”部分并断言字符串和参数是否正确)。

    然后集成测试可以实际执行 SQL 查询以查看测试数据库是否会返回正确的结果。

    当您将集成测试移至 CI 服务器时,您可以满怀信心地运行快速单元测试,因为 CI 服务器最终会在它们中断时通知您。

    【讨论】:

    • 直接检查发出的 SQL 是否正确的想法确实很有趣。
    • 它使单元测试非常快,独立于数据库中的数据(因此无需将复杂的测试用例多次加载到数据库中 + 无需维护数据集),它会准确地告诉您您想知道的内容:代码是否尝试执行正确的 SQL?
    • 使用模拟框架,您甚至可以模拟处理结果。只需创建一个模拟 ResultSet 并将其输入到代码中。
    【解决方案3】:

    从提到的@Aaron Digulla 帖子 (http://blog.pdark.de/2008/07/26/testing-with-databases/) 看来,当开发人员工作站上的本地专用数据库实例成本高昂时,直接在测试中使用数据库最有问题:

    • 数据库是按“每台机器”许可的,因此必须付费 对于这些本地安装。
    • 开发人员实际上无法设置和维护数据库(例如,他们无权访问模式转储)。必须有一个专门的数据库管理员参与进来,这个管理员还有足够多的其他任务要做。
    • 使用专用于测试的共享数据库实例一次只允许一名开发人员,因为必须在运行测试之前擦除架构。
    • 在生产数据库中使用测试模式可能是一场灾难。同意。

    因此,寻找和鼓励替代测试方法的重要性显而易见。

    从这个看起来如果使用开源或其他免费数据库,并且大多数开发人员知道如何安装它,并且在哪里编辑数据库配置文件中的几行以使其运行(只需要完成一次) ,这可能会变得不那么重要,并且无需编写数据库模拟。这个模拟也需要时间来编写。但是,如果一旦编写,mock 比数据库快得多。

    我也完全同意,很多好的测试,很可能是大部分,都可以在完全不参考数据库的情况下编写。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多