Как написать Junit для Spring-amqp с помощью Spring-boot - PullRequest
0 голосов
/ 25 апреля 2019

У меня настроены подписчик и издатель в bean-компоненте @Configuration, я хотел бы написать классы Junit для этих классов конфигурации с использованием макетов. При выполнении теста мне нужно загрузить эти bean-компоненты в контекст Spring, и я хотел бы смоделировать мой слушатель и соединение как фиктивный.

  1. Как смоделировать автоматические зависимости в классе Junit
  2. Как издеваться над аннотированным компонентом Rabbit-Listener в моем тестовом классе

Код выглядит следующим образом.


    @Configuration
    public class ListenerContainerFactory {

        static final Logger logger = LoggerFactory.getLogger(ListenerContainerFactory.class);

        @Autowired
        RabbitMqConfig rabbitMqConfig;

        @Autowired
        EPPQ2Subscriber receiver;



         public ListenerContainerFactory(ConfigurableApplicationContext ctx) {
            printContainerStartMsg();
        }
        private void printContainerStartMsg() {
            logger.info("----------- Scrubber Container Starts   --------------");
        }

        @Bean
        public CachingConnectionFactory subscriberConnectionFactory() {
            CachingConnectionFactory subsCachingConnectionFactory = new CachingConnectionFactory(rabbitMqConfig.getSubscriberHosts(),
                    rabbitMqConfig.getSubscriberPort());
            subsCachingConnectionFactory.setUsername(rabbitMqConfig.getSubscriberUsername());
            subsCachingConnectionFactory.setPassword(rabbitMqConfig.getSubscriberPassword());
            subsCachingConnectionFactory.setVirtualHost("hydra.services");
            subsCachingConnectionFactory.setConnectionNameStrategy(f -> "subscriberConnection");
            return subsCachingConnectionFactory;
        }

        @Bean
        public SimpleRabbitListenerContainerFactory queueListenerContainer(
                @Qualifier("subscriberConnectionFactory") CachingConnectionFactory subscriberConnectionFactory,
                MessageListenerAdapter listenerAdapter) { 
            /*connectionFactory.setAddresses(rabbitMqConfig.getSubscriberHosts());
            connectionFactory.setVirtualHost("hydra.services");
            connectionFactory.setPort(rabbitMqConfig.getSubscriberPort());
            connectionFactory.setUsername(rabbitMqConfig.getSubscriberUsername());
            connectionFactory.setPassword(rabbitMqConfig.getSubscriberPassword());*/
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
            factory.setConnectionFactory(subscriberConnectionFactory);
            factory.setErrorHandler(errorHandler());
            return factory;
        }

         @Bean
         MessageListenerAdapter listenerAdapter(EPPQ2Subscriber receiver) {
             return new MessageListenerAdapter(receiver, "receiveMessage");
         }

         @Bean
            public ErrorHandler errorHandler() {
                return new ConditionalRejectingErrorHandler(fatalExceptionStrategy());
            }

         @Bean
         public  ScrubberFatalExceptionStrategy fatalExceptionStrategy() {
             return new ScrubberFatalExceptionStrategy();
         }
    }

    @Component
    @Configuration
    public class EPPQ2ListenerConfigurer implements RabbitListenerConfigurer{

        public EPPQ2ListenerConfigurer(ConfigurableApplicationContext ctx) {
            // TODO Auto-generated constructor stub
        }

        @Override
        public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
            registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
        }

        @Bean
        MessageHandlerMethodFactory messageHandlerMethodFactory() {
            DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();
            messageHandlerMethodFactory.setMessageConverter(consumerJackson2MessageConverter());
            return messageHandlerMethodFactory;
        }

        @Bean
        public MappingJackson2MessageConverter consumerJackson2MessageConverter() {
            return new MappingJackson2MessageConverter();
        }

    }


Я пробовал что-то подобное, но не работает.

    @ActiveProfiles("test")
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {
            RabbitListenerContainerFactoryTest.TestSetup.class,
            AppConfig.class,
            RabbitMqConfig.class,
            ListenerContainerFactory.class,
            EPPQ2ListenerConfigurer.class,
            EPPQ2Subscriber.class,
            EPPQ2PublisherImpl.class})
    public class RabbitListenerContainerFactoryTest {

        @Autowired
        private AppConfig appConfig; 

        @Autowired
        private SimpleMessageListenerContainer queueListenerContainer;

        @Autowired
        private MessageListenerAdapter listenerAdapterWithChanel;

        @Test
        public void container_bean_should_not_null() {
            assertThat(queueListenerContainer,is(notNullValue()));
        }

        @Test
        public void listener_adapoter_bean_should_not_null() {
            assertThat(listenerAdapterWithChanel,is(notNullValue()));
        }

        @After
        public void cleanup() {
            appConfig.setReadyToGraccefullyExit(true);
        }

        @Configuration
        static class TestSetup {

            @Bean
            public RabbitTemplate rabbitTemplate() throws IOException, TimeoutException {
                ConnectionFactory mockConnectionFactory = mock(ConnectionFactory.class);
                Connection mockConnection = mock(Connection.class);
                Channel mockChannel = mock(Channel.class);

                given(mockConnectionFactory.newConnection(any(ExecutorService.class), anyString())).willReturn(mockConnection);
                given(mockConnection.isOpen()).willReturn(true);
                given(mockConnection.createChannel()).willReturn(mockChannel);

                given(mockChannel.isOpen()).willReturn(true);

                CachingConnectionFactory connectionFactory = new CachingConnectionFactory(mockConnectionFactory);
                connectionFactory.setExecutor(mock(ExecutorService.class));
                RabbitTemplate template = new RabbitTemplate(connectionFactory);

                RetryTemplate retryTemplate = new RetryTemplate();
                ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
                backOffPolicy.setInitialInterval(500);
                backOffPolicy.setMultiplier(10.0);
                backOffPolicy.setMaxInterval(10000);
                retryTemplate.setBackOffPolicy(backOffPolicy);
                template.setRetryTemplate(retryTemplate);
                template.setConfirmCallback((correlation, ack, reason) -> {
                    if(correlation != null ) {
                        System.out.println("Received " + (ack ? " ack " : " nack ") + "for correlation: " + correlation);
                        if(ack) {
                            // this is confirmation received..
                            // here is code to ack Q1. correlation.getId() and ack it !!
                            //eppQ2Publisher.ackMessage(new Long(correlation.getId().toString()));
                            System.out.println("inside Ack");
                        } else {
                            // no confirmation received and no need to do any thing for retry..
                        }
                    }

                });
                template.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
                    System.out.println("Returned: " + message + "\nreplyCode: " + replyCode
                            + "\nreplyText: " + replyText + "\nexchange/rk: " + exchange + "/" + routingKey);
                });
                return template;
            }

            @Bean
            public Channel channel() {
                Channel channel = mock(Channel.class);
                return channel;
            }
        }
    }
...