我最近被要求有效地出售我的部门进行单元测试。我不能告诉你这让我有多兴奋,但我确实有一个问题。我们在Spring和Maven中使用JUnit,这意味着每次调用mvn test
时,它都会重建数据库。显然,我们无法将它与我们的生产服务器集成 - 它会杀死有价值的数据。
如何在不告诉maven跳过测试的情况下阻止重建?
我能想到的最好的方法是将脚本指定为在测试数据库中运行(为了便于阅读,添加了换行符):
mvn test
-Ddbunit.schema=<database>test
-Djdbc.url=jdbc:mysql://localhost/<database>test?
createDatabaseIfNotExist=true&
useUnicode=true&characterEncoding=utf-8
我不禁想到必须有更好的方法。
我特别感兴趣的是学习是否有一种简单的方法可以告诉Maven只在特定类上运行测试而不构建其他任何东西? mvn -Dtest=<test-name> test
仍在重建数据库。
======= update =======
我脸上有点鸡蛋。我没有意识到我在两个地方使用相同的变量,这意味着POM使用“skip.test”变量来重建数据库和运行测试......
答案 0 :(得分:2)
更新:我想DBUnit会重建数据库,因为它会在测试设置方法中告知它。如果更改设置方法,则可以消除数据库重建。当然,您应该这样做,以便在需要时重置数据库,并在不需要时省略它。我的第一个赌注是使用系统属性来控制它。您可以使用与jdbc.url
等人相同的方式在命令行上设置属性。然后在设置方法中添加if
以测试该属性,并在设置时重置数据库。
与生产数据库完全分离的测试数据库绝对是您拥有它的最佳选择。你甚至可以使用例如Derby,一个可以在JVM中嵌入的内存数据库。但是如果您绝对不能拥有单独的数据库,请在该数据库中至少使用一个单独的测试模式。
在这种情况下,我建议您将数据库连接参数放入pom中的配置文件,默认为测试数据库,以及包含生产设置的单独配置文件。这样,您不会意外地对生产数据库运行测试。
但是,一般情况下,理解针对数据库运行的测试并不是严格意义上的单元测试,而是集成测试。如果您有一组现有的此类测试,那么请尽可能多地使用它们。但是,您应该尝试添加更多真实的单元测试,这些测试一次只测试代码的一小部分(最多是一个方法或类),理想情况下是自包含的(不需要DB,net,配置文件等)。 )所以他们可以跑得快 - 这是非常重要的一点。如果你有5000个单元测试,每个测试只需要5秒钟,总计最多可以运行7个小时,所以你显然不会经常运行它们。如果测试只需要5毫秒,您可以在不到半分钟的时间内获得结果,因此您可以在提交最新更改之前运行所有测试 - 每天多次。这会使您从测试中获得的反馈速度产生巨大差异。
希望这有帮助。
答案 1 :(得分:1)
我们在Spring和Maven中使用JUnit,这意味着每次调用mvn test时,它都会重建数据库。
Maven对数据库本身没有任何作用,你的代码也是如此。无论如何,对生产数据库运行测试(不是单元测试)是非常不寻常的。
如何在不告诉maven跳过测试的情况下阻止重建?
很难说没有更多详细信息(您没有显示任何内容),但可能的配置文件是一种方法。
答案 2 :(得分:0)
根据定义,单元测试仅对系统中的单个组件进行操作。您不应该尝试编写与任何外部服务(Web,DB等)集成的单元测试。我必须解决的问题是使用一个好的模拟框架来删除组件所具有的任何依赖项的行为。这鼓励了良好的接口API,因为大多数模拟框架最适合使用简单的接口。最好为与数据库的任何交互创建一个Repository模式接口,然后在测试与之交互的类时模拟impl。然后,您可以单独在功能上测试您的Repository impl。这还有一个额外的好处,就是让您的单元测试足够快,以便成为CI的一部分,以便您的反馈周期尽可能快。