junit spring jms监听器 [英] junit spring jms listener

查看:123
本文介绍了junit spring jms监听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对下面的简单jms侦听器代码进行单元测试

I want to unit test a simple jms listener code below

@Component
public class NotificationReader {

    @JmsListener(destination = "myAppQ")
    public void receiveMessage(NotificationMessage notificationMessage) {
        System.out.println("Received <" + notificationMessage.getStaffNumber() + ">");
    }

}

我从junit使用jmsTemplate将消息发送到Active MQ.

From the junit, I am using jmsTemplate to pump the message into Active MQ.

我想测试是否调用了jms侦听器.

I want to test if the jms listener got invoked.

我看到的解决方案很少(使用计数器),例如

I saw few solutions ( using counters ) like How to wait for @JMSListener annotated method to complete in JUnit, which actually changes the listener code just for testing purpose which I dont want to do.

还有其他选择吗?

尝试按照答案中的建议进行配置.

Tried with configuration as suggested in the answer .

@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自动装配就会失败

Once I add the testConfig , the JMSTempate autowiring fails

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封装在代理中(用于测试用例),并使用闩锁并验证接收到的对象是否符合您的期望...

Wrap your listener bean in a proxy (for the test case) and use a latch and verify that the object received is what you expected...

@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;
                    }
                }

            };
        }

    }

}

编辑

以上内容基于使用Java 8的Spring Framework 5或更高版本,并提供了两个BeanPostProcessor方法的默认实现.

The above is based on Spring Framework 5 or later which uses Java 8 and provides default implementations for both BeanPostProcessor methods.

如果您使用的是较早版本的Spring,则还需要

If you are using an earlier version of Spring you will also need

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

BPP也应为static.

这篇关于junit spring jms监听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆