所以我试图让JMS处理,春季(v4.1.6)基于代码的集成测试。
这是一个非常标准的Spring设置与@JmsListener
标注的方法和DefaultMessageListenerContainer
与concurrency
设置为1
,因此只允许1监听线程。
现在,我利用ActiveMQ的嵌入式代理不依赖于任何外部JMS代理的测试,随时随地运行(我应该在市场营销工作)。
因此,所有导线细,然后我有我的JUnit测试:
@Test
public void test() {
sendSomeMessage();
//how to wait here for the @JMSListener method to complete
verify();
}
我发送消息,但后来我需要以某种方式等待@JMSListener
批注的方法来完成。 我该怎么做呢?
好吧,我希望我能以某种方式挂接到驱动的POJO生命周期做这个消息,而是通过其他会这么了解异步代码的问题,我有一个解决方案提出了基于CountDownLatch
该@JMSListener
annotaded方法应该调用countDown()
上的CountDownLatch所有工作完成后:
@JmsListener(destination = "dest", containerFactory = "cf") public void processMessage(TextMessage message) throws JMSException { //do the actual processing actualProcessing(message); //if there's countDownLatch call the countdown. if(countDownLatch != null) { countDownLatch.countDown(); } }
在TestMethod的
@Test public void test() throws InterruptedException { //initialize the countDownLatch and set in on the processing class CountDownLatch countDownLatch = new CountDownLatch(1); messageProcessor.setCountDownLatch(countDownLatch); //sendthemessage sendSomeMessage(); //wait for the processing method to call countdown() countDownLatch.await(); verify(); }
这种解决方案的缺点是,你必须真正改变你的@JMSListener
专门标注的方法的集成测试
为了避免改变你的实际@JmsListener方法,你可以尝试和测试使用AOP ...
首先创建一个方面类是这样的:
@Aspect
public static class JmsListenerInterceptor {
@org.aspectj.lang.annotation.After("@annotation(org.springframework.jms.annotation.JmsListener)")
public void afterOnMessage(JoinPoint jp) {
// Do countdown latch stuff...
}
}
然后在你的应用程序上下文配置中添加它,你正在使用的测试,像这样:
<aop:aspectj-autoproxy/>
<bean id="jmsListenerInterceptor" class="path.to.your.Test$JmsListenerInterceptor" />
如果一切按计划进行,该JmsListenerInterceptor会倒计时,你不必改变你的实际代码。
重要提示:我刚刚发现,使用AOP和对的Mockito验证是否在你的@JmsListener某些方法被调用是一个糟糕的组合。 原因似乎是多余的包装到导致错误的/实际的目标实例CGLIB类被调用,而不是代理的Mockito。
在我的测试中,我有一个@Autowired,@InjectMocks 监听对象和@Mock 门面对象,我想验证某种方法被调用。
随着AOP:
- 测试主题:
- [JmsListenerTest] 2279812 -类侦听$$ EnhancerBySpringCGLIB $$ 6587f46b(由Spring AOP包裹)
- [JmsListenerTest] 30960534 -类门面$$ EnhancerByMockitoWithCGLIB $$ 69fe8952(由缠绕的Mockito)
- 监听线程:
- [监听] 1151375 -类侦听器(靶向AOP包裹类的实例)
- [听众] 4007155 -类FacadeImpl(而不是实际的情况下,我们预期)
没有AOP:
- 测试主题:
- [JmsListenerTest] 10692528 -类侦听器(实际的实例)
- [JmsListenerTest] 823767 -类门面$$ EnhancerByMockitoWithCGLIB $$ 773538e8(由缠绕的Mockito)
- 监听线程:
- [听众] 10692528 -类侦听器(仍然实际实例)
- [听众] 823767 -类门面$$ EnhancerByMockitoWithCGLIB $$ 773538e8(仍然是我们嘲笑实例)
这一切都表明,你需要注意使用AOP我想顺便说一下,你可能最终在两个线程不同的情况下...
如果你想补充记录到@JmsListener注解的方法,你可以做这样的事情在测试类
@Rule
public OutputCapture outputCapture = new OutputCapture();
@Test
public void test() {
sendSomeMessage();
//how to wait here for the @JMSListener method to complete
Assertions.assertThat(outputCapture.toString()).contains("Message received.");
}