私はユニットテストにJUnitのからJUnitのバネJMSリスナー
@Component
public class NotificationReader {
@JmsListener(destination = "myAppQ")
public void receiveMessage(NotificationMessage notificationMessage) {
System.out.println("Received <" + notificationMessage.getStaffNumber() + ">");
}
}
以下の単純なJMSリスナーコードをしたい、私は、Active MQにメッセージをポンプするためにjmsTemplateを使用しています。
jmsリスナーが呼び出されたかどうかをテストします。
How to wait for @JMSListener annotated method to complete in JUnitのようないくつかの解決策(カウンターを使用)を見ましたが、私がやりたくないテスト目的のためにリスナーコードを実際に変更しています。
他の方法はありますか?
回答で示唆されているように設定を試してみてください。
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestNotificationReader {
@Autowired
JmsTemplate jmsTemplate;
@Value("${outbound.endpoint}")
private String destination;
@Test
public void contextLoads() {
}
@Test
public void testPutToQ() {
NotificationMessage notificationMessage = new NotificationMessage();
notificationMessage.setStaffNumber("100");
notificationMessage.setWorkflowType("TYPE");
notificationMessage.setWorkflowId("100");
notificationMessage.setWorkflowDescription("Test From Queue");
jmsTemplate.convertAndSend(destination, notificationMessage);
jmsTemplate.setReceiveTimeout(10000);
try {
TestConfig.latch.await(10, TimeUnit.SECONDS);
NotificationMessage temp = (NotificationMessage) TestConfig.received;
System.out.println(" temp.getStaffNumber() " + temp.getStaffNumber());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Configuration
public static class TestConfig {
private static final CountDownLatch latch = new CountDownLatch(1);
private static Object received;
@Bean
public static BeanPostProcessor listenerWrapper() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof NotificationReader) {
MethodInterceptor interceptor = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = invocation.proceed();
if (invocation.getMethod().getName().equals("receiveMessage")) {
received = invocation.getArguments()[0];
latch.countDown();
}
return result;
}
};
if (AopUtils.isAopProxy(bean)) {
((Advised) bean).addAdvice(interceptor);
return bean;
} else {
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.addAdvice(interceptor);
return proxyFactory.getProxy();
}
} else {
return bean;
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
return bean;
}
};
}
}
}
私はtestConfigを追加すると、JMSTempateのオートワイヤリングは
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.jms.core.JmsTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
BeanPostProcessor()がpostProcessBeforeInitializationを実装しなければならなかったので、このコードをコンパイルできませんでした。この設定を使用すると、既存のBeanの自動配線に失敗したためにコンテキスト・ロードが失敗します。上に提供されているものとは別のコードが必要かどうかをよく確認してください。 – lives
この例はSpring 5.0に基づいています。私の編集を参照してください。もう何も必要ありません。 BPPを静的に宣言してリスナーBeanの前に登録されていることを確認する必要があります。それでも問題が解決しない場合は、質問を編集してCOMPLETE設定とテストを表示してください。 –
あなたの応答を感謝します。私はまだそれを動作させることができませんでした。私はjunitのテストコードを投稿しました – lives