junit spring jms 侦听器
junit spring jms listener
我想对下面的简单 jms 侦听器代码进行单元测试
@Component
public class NotificationReader {
@JmsListener(destination = "myAppQ")
public void receiveMessage(NotificationMessage notificationMessage) {
System.out.println("Received <" + notificationMessage.getStaffNumber() + ">");
}
}
我在 junit 中使用 jmsTemplate 将消息泵入 Active MQ。
我想测试是否调用了 jms 侦听器。
我看到很少有像 这样的解决方案(使用计数器),它实际上只是为了测试目的而更改侦听器代码,我不想这样做。
还有其他选择吗?
尝试按照答案中的建议进行配置。
@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]
将您的侦听器 bean 包装在代理中(用于测试用例)并使用闩锁并验证接收到的对象是否符合您的预期...
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { So48033124Application.class, So48033124ApplicationTests.TestConfig.class })
public class So48033124ApplicationTests {
@Autowired
private JmsTemplate template;
@Test
public void test() throws Exception {
Foo foo = new Foo("bar");
this.template.convertAndSend("foo", foo);
assertThat(TestConfig.latch.await(10, TimeUnit.SECONDS)).isTrue();
assertThat(TestConfig.received).isEqualTo(foo);
}
@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 MyListener) {
MethodInterceptor interceptor = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = invocation.proceed();
if (invocation.getMethod().getName().equals("listen")) {
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;
}
}
};
}
}
}
编辑
以上内容基于 Spring Framework 5 或更高版本,它使用 Java 8 并为两种 BeanPostProcessor
方法提供默认实现。
如果您使用的是 Spring 的早期版本,您还需要
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
BPP 也应该是 static
。
我想对下面的简单 jms 侦听器代码进行单元测试
@Component
public class NotificationReader {
@JmsListener(destination = "myAppQ")
public void receiveMessage(NotificationMessage notificationMessage) {
System.out.println("Received <" + notificationMessage.getStaffNumber() + ">");
}
}
我在 junit 中使用 jmsTemplate 将消息泵入 Active MQ。
我想测试是否调用了 jms 侦听器。
我看到很少有像
还有其他选择吗?
尝试按照答案中的建议进行配置。
@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]
将您的侦听器 bean 包装在代理中(用于测试用例)并使用闩锁并验证接收到的对象是否符合您的预期...
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { So48033124Application.class, So48033124ApplicationTests.TestConfig.class })
public class So48033124ApplicationTests {
@Autowired
private JmsTemplate template;
@Test
public void test() throws Exception {
Foo foo = new Foo("bar");
this.template.convertAndSend("foo", foo);
assertThat(TestConfig.latch.await(10, TimeUnit.SECONDS)).isTrue();
assertThat(TestConfig.received).isEqualTo(foo);
}
@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 MyListener) {
MethodInterceptor interceptor = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = invocation.proceed();
if (invocation.getMethod().getName().equals("listen")) {
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;
}
}
};
}
}
}
编辑
以上内容基于 Spring Framework 5 或更高版本,它使用 Java 8 并为两种 BeanPostProcessor
方法提供默认实现。
如果您使用的是 Spring 的早期版本,您还需要
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
BPP 也应该是 static
。