模拟消息队列(JMS)

28

有一条消息(文本),我确定其格式和内容。
目前,已经实现了一个在Java中从文件解析并读取此消息的类。

在真实世界中,这条消息将来自消息队列。

目前,我应该在我的本地电脑上模拟、模拟或生成消息队列以进行测试。

Java规范(java jms):

JMS provider: A messaging system that implements the JMS specification.
JMS clients: Java applications that send and receive messages.
Messages: Objects that are used to communicate information between JMS clients.
关于这个规范,我需要JMS提供者。 JMS客户端是我的读取消息的类,消息本身我知道。 所以问题是如何启动消息队列? 我如何从Java代码中以编程方式模拟它? 我能否以某种方式进行模拟? 谢谢。

1
为什么要费这么大的劲呢?为什么不在您的工作站上安装本地JMS提供程序并使用它呢?您可以下载开源版本和供应商JMS提供程序的试用版。由于它是JMS,任何符合规范的实现都适用于单元测试。 - T.Rob
这就是我问的,所以我需要安装JMS提供程序。你有什么建议吗?谢谢。 - sergionni
嗯,我是IBM员工,所以我必须建议您尝试WMQ的试用版。 :-) 但我看到您已经找到了ActiveMQ,可以在开发中使用而不会过期。另一方面,您在生产中使用的任何内容都最好在开发时使用,因此一旦确定了它将是什么,就转移到该内容上。 - T.Rob
2
Mockrunner JMS Spring单元测试:模拟JMS队列的简便方法。请参考以下网站:https://dzone.com/articles/mockrunner-jms-spring-unit - Yallaling Goudar
5个回答

11
当实际生产的JMS提供程序不可用时,您可以使用以下一种方法来隔离测试应用程序:
  1. JMS模拟:
    在测试您的应用程序时,您可以使用 测试替身 来模拟不存在的依赖项。您可以使用 JMS 模拟器来模拟真实的 JMS 提供程序行为。使用 API 模拟工具 可以创建 JMS 模拟器(只需选择支持 JMS 的工具,例如 Traffic Parrot)。使用 JMS 模拟器可以允许您在测试期间高度灵活,您可以测试典型的生产测试场景和设置模拟器返回几乎任何类型的消息来测试假设情况。您还可以模拟不同类型的错误,这通常很难在真实的 JMS 提供程序中实现。请参阅 此视频介绍如何使用 ActiveMq 进行 JMS 服务虚拟化(服务虚拟化是模拟的另一个名称)或 此视频介绍如何使用 IBM MQ。请注意,这些视频来自 Traffic Parrot,但所描述的原则适用于您选择的任何工具。

  2. JMS提供程序测试实例:
    您可以在笔记本电脑或其中一个测试环境中运行 JMS 提供程序,并将应用程序连接到它,而不是生产提供程序。当您在生产中使用像 ActiveMQ 或 RabbitMQ 这样的开源提供程序时,也应该很容易在笔记本电脑上运行其中之一,因为它们轻便且免费。对于 IBM Websphere MQ,您可以使用免费的 IBM MQ for Developers

  3. JMS类模拟:
    您可以在单元测试中使用Mockito来模拟与JMS类的交互。这种解决方案具有单元测试的所有权衡。有关更多信息,请参见测试金字塔

如果您想对应用程序进行黑盒测试,请使用我上面描述的其中一种解决方案。


6
如果您使用Spring Integration,那么这个过程就非常容易了。它具有基本的抽象“通道”实现。您可以创建和测试生产者和消费者,当您准备向前迈进一步时,只需在通道之上指定一个JMS适配器即可。

0
与此同时,几乎每个消息代理都有一个嵌入式版本,仅在JVM内部运行。因此,您可以将其用于测试,而不需要依赖外部的JMS代理。

-1
通常模拟或模拟外部系统(例如JMS)是一种不好的做法。更好的想法是将您的逻辑抽象成一个独立的bean,实现一个委托层,将JMS与您的bean桥接起来。通过这样的设计,您可以在与JMS隔离的情况下测试您的bean,然后进行系统测试,以测试与真实JMS系统的整个集成。
至于进程内JMS,您可以查看SomnifugiJMS

45
我完全不同意。在单元测试中,嘲笑外部系统对于您依赖外部接口但不想将单元测试转化为集成测试非常关键。请注意,这里的“mocking”指的是模拟或者伪造外部系统的行为。 - Andres Kievsky
1
@ank - 模拟外部系统是一种不好的做法。解决方案是在您自己的应用程序中创建一个与该系统通信的接口(Eugene Kuleshov所指的bean),然后在测试中模拟它。尝试模拟整个外部系统是昂贵且混乱的。 - Ickster
2
@Ickster 这就是 mock 的定义...(我知道这很旧了,但)你能给出一个你认为在其中做出区分的例子吗? - davemyron
@davemyron -- 很好的问题。我知道当我写下那个东西时,我正在做一些东西,这是我试图表达的完美例子,但可恶的是我现在无法确切地记起来它是什么。如果我想起来了,我会告诉你的。 - Ickster
JMS 在很大程度上是一个接口。因此,虽然有些棘手,但模拟它肯定是可以接受但痛苦的做法之一。如果您正在使用特定实现中的某些内容(似乎许多人都这样做),那么更好的建议可能是“停止这样做”。 - Mykel Alvis
3
最近像http://wiremock.org,https://hoverfly.io/和http://www.mbtest.org/这样的工具越来越流行,用于创建针对HTTP API的进程外(通过网络)模拟。同样的进程外模拟原理也可以应用于支持JMS的API模拟工具中。在这里提到了HTTP,因为它比JMS更受欢迎,而且更容易观察市场趋势。 - Wojtek

-2
通常我同意Eugene Kuleshov的观点。但如果你仍然需要这样的嘲弄,我建议你使用java.util.concurent包中的BlckingQueue。我认为用javax.jms.Queue接口包装它不是一个大问题。顺便说一句,这对于某种开源项目是个好主意。

我刚刚发现了Apache ActiveMQ。这是我第一次尝试使用它。 - sergionni
我也同意Eugene Kuleshov的观点。我认为BDD的创始人Dan North(可能也同意他的观点),以及任何有设计头脑的人都会同意我的想法。如果您将业务逻辑与JMS队列的入口混在一起,那么您的应用程序就犯了设计错误。更好的选择是修复设计错误(如果可以)。然而,有时这是不可能的。您可能正在使用负责关键任务系统的大型遗留代码库,而这些代码库很难在没有变更风险的情况下进行修复。Eugene Kuleshov仍然是正确的。 - John Deverall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接