我有Java应用程序,使用预处理语句对PostgreSQL数据库进行一些JDBC查询。查询不是很复杂,主要是一个衬里,但无论如何我想对它们进行一些单元测试。
最初我编写了一个JUnit测试用例,它连接一个单独的测试数据库(当然不是生产数据库),在启动时擦除它,创建简单的测试内容并激活查询。我被批评为这种方法,因为"数据库不应该用于测试"。
"数据库用于测试的原因"是数据库引擎是我正在测试的代码(SQL)的解释器。在没有数据库的情况下测试SQL的要求听起来像是在没有Java虚拟机的情况下测试Java代码的要求。
声称某些代码由于哲学原因而永远不能进行测试听起来有些奇怪,同样关于大多数SQL特性(如范围或其他更复杂的查询或连接)实际上永远不会被使用的建议。我还使用了一个围绕所有数据库活动的包装类,并且有一个" SQL服务模拟"不与数据库交谈,并在各种其他测试中使用它,但我还需要测试这个模拟的实际生产实现。
是否有替代的,更好的方法来测试我的JDBC查询集,或者我可能没有做错什么?
答案 0 :(得分:1)
Martin Fowler在单元测试中有一篇关于外部依赖关系的文章:
"即使像我这样的经典测试人员也会在尴尬的合作中使用测试双打。在与远程服务交谈时,它们对于消除非确定性非常有用。事实上,一些古典主义的xunit测试人员也认为,任何与外部资源(如数据库或文件系统)的协作都应该使用双精度。部分原因是由于非确定性风险,部分原因是速度。" http://martinfowler.com/bliki/UnitTest.html
就个人而言,我认为如果您的测试设置其上下文而不是依赖可能并非总是可用的外部系统,那就没问题了。
答案 1 :(得分:0)
我在本博文中概述了我在单元测试中避免使用数据库的原因:http://blog.pdark.de/2008/07/26/testing-with-databases/
总结一下:你在测试什么? PostgreSQL的?为什么?他们已经有数以千计的单元测试,以确保数据库按预期工作?
你为什么要测试PostgreSQL?您应该测试您的代码。你之所以没有这种唠叨的感觉,我可能会错过一些东西。"这种感觉的来源是你不确切知道自己在做什么。本能的本能是淹没大量代码中的焦虑(就像在单元测试中执行更多代码会使其以任何方式变得更好)。
解决方案:尝试将创建SQL查询的代码与实际执行它的代码分开。这样,您可以轻松地拆分单元和集成测试。单元测试只是检查你的代码是否生成了正确的SQL(只需调用"创建SQL查询"部分并断言字符串和参数是正确的。)
然后,集成测试可以实际执行SQL查询,以查看测试数据库是否会返回正确的结果。
当您将集成测试移动到CI服务器时,您可以非常自信地运行快速单元测试,因为CI服务器会在它们中断时最终通知您。
答案 2 :(得分:0)
从提到的@Aaron Digulla帖子(http://blog.pdark.de/2008/07/26/testing-with-databases/)看起来直接在测试中使用数据库在开发人员工作站上的本地专用数据库实例很昂贵时会出现问题:
因此,很明显找到并鼓励其他测试方法的重要性。
从这看起来如果使用开源或其他免费数据库,并且大多数开发人员知道如何安装它,并且在数据库配置文件中编辑几行以使其运行(只需要执行一次) ,这可能不再是一个问题,并消除了编写数据库模拟的需要。这个模拟也需要时间来写。但是,如果一旦编写,模拟比数据库快得多。
我也完全同意,可以在不引用数据库的情况下编写许多优秀的测试,很可能是大部分测试。