With @Gary Russell, I was able to get an answer and used the following solution.
Conclusion: I have to admit that I am indifferent to this decision (it seems like a hack), but this is the only thing I could get, and as soon as you go to the initial time setting and actually understand the “workflow”, this not so painful. It basically boils down to defining (2) @ Beans and adding them to the Test Integration configuration.
An approximate solution is published below with explanations. Feel free to suggest improvements to this solution.
1. Define ProxyListenerBPP that spring initialization will listen for a specific clazz (that is, our test class containing @RabbitListener) and add our special request CountDownLatchListenerInterceptor, defined in the next step.
import org.aopalliance.aop.Advice; import org.springframework.aop.framework.ProxyFactoryBean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; public class ProxyListenerBPP implements BeanPostProcessor, BeanFactoryAware, Ordered, PriorityOrdered{ private BeanFactory beanFactory; private Class<?> clazz; public static final String ADVICE_BEAN_NAME = "wasCalled"; public ProxyListenerBPP(Class<?> clazz) { this.clazz = clazz; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (clazz.isAssignableFrom(bean.getClass())) { ProxyFactoryBean pfb = new ProxyFactoryBean(); pfb.setProxyTargetClass(true);
2. Create a MethodInterceptor recommendation that will reference the CountDownLatch. CountDownLatch must be referenced both in the integration test stream and inside the async workflow in @RabbitListener. This way, we will be able to return to the integration test thread later , as soon as the asynchronous @RabbitListener stream has completed execution. No survey needed.
import java.util.concurrent.CountDownLatch;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class CountDownLatchListenerInterceptor implements MethodInterceptor { private CountDownLatch countDownLatch = new CountDownLatch(1); private final String methodNameToInvokeCDL ; public CountDownLatchListenerInterceptor(String methodName) { this.methodNameToInvokeCDL = methodName; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { String methodName = invocation.getMethod().getName(); if (this.methodNameToInvokeCDL.equals(methodName) ) {
3. Next add to your integration test Configure the following @ Bean (s)
public class SomeClassThatHasRabbitListenerAnnotationsITConfig extends BaseIntegrationTestConfig {
4. Finally, in the integration call @Test ... after sending the message via rabbitTemplate to start the asynchronous stream ... the method CountDownLatch # wait (...) is now called from the interceptor and do not forget to pass the TimeUnit arguments so that it can time-out out in the case of a long process or something went wrong. As soon as the asynchronous flow of the integration test is notified (awakened), and now we can finally begin to actually check / verify / verify the results of the async operation.
@ContextConfiguration(classes={ SomeClassThatHasRabbitListenerAnnotationsITConfig.class } ) public class SomeClassThatHasRabbitListenerAnnotationsIT extends BaseIntegrationTest{ @Inject private CountDownLatchListenerInterceptor interceptor; @Inject private RabbitTemplate rabbitTemplate; @Test public void shouldReturnBackAfterAsyncThreadIsFinished() throws Exception { MyObject payload = new MyObject(); rabbitTemplate.convertAndSend("some.defined.work.queue", payload); CountDownLatch cdl = interceptor.getCountDownLatch();