我有一个类,它在做了一些事情之后,会发送一条 JMS 消息。我想对“东西”进行单元测试,但不一定是发送消息。
当我运行我的测试时,“东西”绿色条,但在发送消息时失败(它应该,应用程序服务器没有运行)。最好的方法是什么,是模拟消息队列,如果是,那是如何完成的。
我正在使用 Spring,并且“jmsTemplate”与“queue”一起被注入。
5 回答
我会使用的最简单的答案是删除消息发送功能。例如,如果你有这个:
public class SomeClass {
public void doit() {
//do some stuff
sendMessage( /*some parameters*/);
}
public void sendMessage( /*some parameters*/ ) {
//jms stuff
}
}
然后我会编写一个测试来掩盖 sendMessage 行为。例如:
@Test
public void testRealWorkWithoutSendingMessage() {
SomeClass thing = new SomeClass() {
@Override
public void sendMessage( /*some parameters*/ ) { /*do nothing*/ }
}
thing.doit();
assertThat( "Good stuff happened", x, is( y ) );
}
如果被存根或隐藏的代码量很大,我不会使用匿名内部类,而只是使用“普通”内部类。
您可以注入一个模拟的 jmsTemplate。
假设easymock,类似
JmsTemplate mockTemplate = createMock(JmsTemplate.class)
这样就行了。
另一个选择是MockRunner,它为 JDBC、JMS、JSP、JCA 和 EJB 提供模拟环境。这使您可以像在“真实”情况下一样定义队列/主题并简单地发送消息。
关于如何在更大的应用程序中组织所有这些测试存根/模拟......
我们构建和维护一个更大的企业应用程序,它是用 Spring 配置的。真正的 App 在 JBoss Appserver 上作为 EAR 运行。我们用 beanRefFactory.xml 定义了 Spring 上下文
<bean id="TheMegaContext"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>BasicServices.xml</value>
<value>DataAccessBeans.xml</value>
<value>LoginBeans.xml</value>
<value>BussinessServices.xml</value>
....
</list>
</constructor-arg>
</bean>
为了运行单元测试,我们只使用不同的 beanRefFactory.xml,它交换 BasicServices 以使用测试版本。在该测试版本中,我们可以使用与生产版本中相同的名称定义 bean,但使用模拟/存根或任何实现(例如,数据库使用本地 Apache DPCP 池数据源,而生产版本使用来自 Appserver 的数据源)。
这是使用 jMock 单元测试的理想选择,因为您的服务器没有运行,但您将使用 jMock 来模拟与服务器的交互。