多语言堆栈的集成测试(Java/MongoDB/RabbitMQ...)
Posted
技术标签:
【中文标题】多语言堆栈的集成测试(Java/MongoDB/RabbitMQ...)【英文标题】:Integration tests of a polyglot stack (Java/MongoDB/RabbitMQ...) 【发布时间】:2013-02-18 16:31:08 【问题描述】:我知道 RabbitMQ 是用 Erlang 编写的,因此不能像我们使用 ActiveMQ JMS 代理那样嵌入到 JVM 中。
但实际上有些项目是用另一种语言完成的,可以很容易地嵌入到集成测试中。
例如,用 C++ 编写的 MongoDB 可以在 JVM 集成测试的上下文中轻松启动/停止: https://github.com/flapdoodle-oss/embedmongo.flapdoodle.de
还有人将其移植到 Java: https://github.com/thiloplanz/jmockmongo/
所以我只是想知道,当我的应用程序是用 Java 编写的,而其他技术是另一种语言(如用于 RabbitMQ 的 Erlang)时,我们如何进行集成测试?
一般来说,有哪些好的做法?
我看到了 3 个主要解决方案:
启动一个真正的 RabbitMQ 在当前使用的语言中嵌入技术的 JVM 端口 使用标准技术,以便 Erlang 中的一种技术可以具有与 Java 中的另一种技术相同的行为和通信层(RabbitMQ / Qpid / StormMQ 实现 AMQP)是否有用于启动临时 RabbitMQ 代理的 Maven/Sbt/Ant 插件? 有没有在测试课前支持 Junit/TestNG RabbitMQ 的项目?
我看到有一个 AMQP 在 Java 中的开源实现:Apache Qpid 在生产中有 RabbitMQ 时,有人有使用此实现进行集成测试的经验吗?甚至可能吗? 我正在使用 Spring 集成。
顺便说一句,我刚刚注意到 Spring-AMQP 项目在其 github 自述文件中提到:
这里的许多“集成”测试需要一个正在运行的 RabbitMQ 服务器 - 如果没有检测到代理,它们将被跳过。
【问题讨论】:
我在另一个 JVM 项目中使用 Apache Qpid 的经历确实令人失望。虽然以这种方式启动 Apache Qpid 是可能的,但它并不是为这样工作而设计的。 QPid 在运行时重新配置了整个应用程序日志框架(SLF4J + Logback)以满足自己的需求,并且不容易恢复这种变化。在我们的案例中,我们严重依赖 RabbitMQ 的扩展,因此不再追求这条道路没有意义。 【参考方案1】:由于我处于与您完全相同的情况并且找不到好的解决方案,因此我自己开发了它(受 Embedded-Redis、Embedded-Mongo 等启发)
这个库是下载、提取、启动和管理 RabbitMQ 过程的包装器,因此它可以像任何 JVM 项目控制的嵌入式服务一样工作。
查看:https://github.com/AlejandroRivera/embedded-rabbitmq
很简单:
EmbeddedRabbitMqConfig config = new EmbeddedRabbitMqConfig.Builder()
.version(PredefinedVersion.V3_5_7)
// ...
.build();
EmbeddedRabbitMq rabbitMq = new EmbeddedRabbitMq(config);
rabbitMq.start();
...
rabbitMq.stop();
适用于 Linux、Mac 和 Windows。
【讨论】:
【参考方案2】:根据 Philip Christiano 的回答说要使用 VM,现在我们有了 Docker,我认为这是在 docker 容器中嵌入不同技术的方法。
可以启动一个包含 RabbitMQ 服务器的 docker 容器,它会比使用 VM 更快,因为 docker 容器是轻量级的,并且启动时间要好得多。
有一些 maven 插件允许启动 docker 容器,例如:http://www.alexecollins.com/content/docker-maven-plugin/
【讨论】:
【参考方案3】:我会告诉你我对 Apache QPid 与 Rabbit MQ 的看法,因为我使用了这两者。我的观点是他们确实“扩展”了 AMQP,但是却大不相同。如果在生产中您将拥有 Rabbit MQ,则在测试中使用相同的 - 也相同的版本、补丁、修复等。有些事情 Apache Qpid 可以做,而 Rabbit MQ 不能,反之亦然。
说明显而易见的集成测试已完成,以便您可以测试应用程序的集成。我会启动一个 Rabbit MQ 实例。
【讨论】:
是的,没错。顺便说一句,RabbitMQ 似乎是 AMQP 0.9.1 代理,但 Qpid 是 1.0... 我也会启动一个 RabbitMQ 实例,但是对于自动化/CI 测试,你如何启动它?我想要一些用于预集成测试阶段的 maven 插件,它会生成一个全新的 RabbitMQ 服务器并在测试后将其关闭【参考方案4】:过去,我使用过一个运行全新安装的 RabbitMQ 的虚拟机。开发人员会不断地运行它,我们的 CI 服务器将为代码的每个修订启动一个新的 VM。如果他们无法连接到服务器而不是跳过测试,我们的测试将会失败,因为缺乏集成测试是一个严重的问题。
这往往工作得相当好,并防止需要启动和停止 RabbitMQ 进行测试。我们的测试被拆分为使用虚拟主机进行隔离和一些调用来按需创建虚拟主机,这样我们就可以在需要时并行化测试。
【讨论】:
好主意。使用 RabbitMQ 生成该 VM 需要多长时间? 使用 Vagrant 和缓存 basebox 需要不到 5 分钟,这在 CI 机器上有点问题,因此在测试运行后重建它以等待下一次代码推送。通过对虚拟主机进行适当的管理,应该可以让它为 CI 服务器运行并在一夜之间重建它。 我看到有一个 maven vagrant 插件。需要尝试一下。 nicoulaj.github.io/vagrant-maven-plugin/examples/… 谢谢这似乎是最好的使用方式 我在这里接受了我自己的答案:***.com/a/24919210/82609 因为在我看来,使用 Docker 似乎比最终使用虚拟机更合适【参考方案5】:如果是我,我会考虑模拟有问题的堆栈组件。 What's the best mock framework for Java?(虽然不是一个很好的 Stack Overflow 问题)和 Mock Object 可能会帮助您继续前进。
模拟组件比尝试“实时测试”所有内容更容易(恕我直言)。
【讨论】:
我们已经使用了模拟(顺便说一句,我和一个 Mockito 提交者一起工作)。此集成测试旨在检查集成是否有效。所以如果我使用模拟,这部分不再测试。我想检查我的损坏配置是否也适用于我的应用程序,而不仅仅是应用程序行为。以上是关于多语言堆栈的集成测试(Java/MongoDB/RabbitMQ...)的主要内容,如果未能解决你的问题,请参考以下文章