Пример RabbitListenerConfigureIntegrationTests - PullRequest
1 голос
/ 15 марта 2019

Я ищу несколько примеров интеграционных тестов для RabbitListenerConfigurer и RabbitListenerEndpointRegistrar, вызываю аннотацию @rabbitListner, проверяю конвертацию сообщений и передаю дополнительные параметры, такие как свойства канала и сообщения и т. Д. Что-то вроде этого

@RunWith(SpringJUnit4ClassRunner.class)
public class RabbitListenerConfigureIntegrationTests {

    public final String sampleMessage="{\"ORCH_KEY\":{\"inputMap\":{},\"outputMap\":{\"activityId\":\"10001002\",\"activityStatus\":\"SUCCESS\"}}}";

    @Test
    public void testRabiitListenerConfigurer() throws Exception {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
                EnableRabbitConfigWithCustomConversion.class);
        RabbitListenerConfigurer registrar = ctx.getBean(RabbitListenerConfigurer.class);
        /* I want to get the Listener instance here */
        Message message = MessageBuilder.withBody(sampleMessage.getBytes())
                 .andProperties(MessagePropertiesBuilder.newInstance()
                .setContentType("application/json")
                .build())
                 .build();
        /* call listener.onmessage(message) and that intern pass the call back to @rabbit listener and by that time MessageHandler which is registered should kick off and convert the message */
    }

    @Configuration
    @EnableRabbit
    public static class EnableRabbitConfigWithCustomConversion implements RabbitListenerConfigurer {

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

        }

        @Bean
        public ConnectionFactory mockConnectionFactory() {
            return mock(ConnectionFactory.class);
        }

        @Bean
        public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factory.setConnectionFactory(mockConnectionFactory());
            factory.setAutoStartup(false);
            return factory;
        }

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

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

        @Bean 
        public  Listener messageListener1() {
            return new Listener();
        }

    }

public class Listener {

    @RabbitListener(queues = "QUEUE")
    public void listen(ExchangeDTO dto, Channel chanel) {
        System.out.println("Result:" + dto.getClass() + ":" + dto.toString());
        /*ExchangeDTO dto = (ExchangeDTO)messageConverter.fromMessage(message);
        System.out.println("dto:"+dto);*/
    }
}

РЕДАКТИРОВАТЬ 2 Я не получаю Exchange DTO заполнены значениями.вместо этого я получаю нулевые значения. Вот лог: 15: 00: 50.994 [main] DEBUG org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter - Обработка [GenericMessage [payload = byte [93], headers = {contentType = application /json, id = 8bf86bf1-7e45-d136-9126-69959f92f100, отметка времени = 1552680050993}]] Результат: класс com.dsicover.dftp.scrubber.subscriber.ExchangeDTO: DTO [inputMap = {}, outputMap = {}]

public class ExchangeDTO implements Serializable {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private HashMap<String, Object> inputMap = new HashMap<String, Object>();
        private HashMap<String, Object> outputMap = new HashMap<String, Object>();

        public HashMap<String, Object> getInputMap() {
            return inputMap;
        }

        public void setInputMap(HashMap<String, Object> inputMap) {
            this.inputMap = inputMap;
        }

        public HashMap<String, Object> getOutputMap() {
            return outputMap;
        }

        public void setOutputMap(HashMap<String, Object> outputMap) {
            this.outputMap = outputMap;
        }

        @Override
        public String toString() {
            return "DTO [inputMap=" + this.inputMap + ", outputMap=" + this.outputMap + "]";
        }
}

Есть ли что-то, чего мне не хватает в Jackson2MessageConverter.

Ответы [ 2 ]

0 голосов
/ 15 марта 2019
  • Дайте @RabbitListener id
  • RabbitListenerEndpointRegistry.getListenerContainer(id);
  • литой контейнер до AbstractMessageListenerContainer
  • container.getMessageListener()
  • приведение слушателя к ChannelAwareMessageListener
  • Звоните onMessage().
  • использовать фиктивный канал и проверить ожидаемый вызов

EDIT

@Autowired
private RabbitListenerEndpointRegistry registry;

@Test
public void test() throws Exception {
    AbstractMessageListenerContainer listenerContainer =
            (AbstractMessageListenerContainer) this.registry.getListenerContainer("foo");
    ChannelAwareMessageListener listener =
            (ChannelAwareMessageListener) listenerContainer.getMessageListener();
    Channel channel = mock(Channel.class);
    listener.onMessage(new Message("foo".getBytes(),
            MessagePropertiesBuilder
                .newInstance()
                .setDeliveryTag(42L)
                .build()), channel);
    verify(channel).basicAck(42L, false);
}

EDIT2

Ваш JSON не похож на DTO, он выглядит как Map<String, DTO>.

Это прекрасно работает для меня ...

@SpringBootApplication
public class So55188061Application {

    public static void main(String[] args) {
        SpringApplication.run(So55188061Application.class, args);
    }

    @RabbitListener(id = "foo", queues = "foo")
    public void listen(Map<String, Foo> in, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        System.out.println(in);
        channel.basicAck(tag, false);
    }

    @Bean
    public MessageConverter converter() {
        return new Jackson2JsonMessageConverter();
    }

    public static class Foo {

        private HashMap<String, Object> inputMap = new HashMap<String, Object>();

        private HashMap<String, Object> outputMap = new HashMap<String, Object>();


        public HashMap<String, Object> getInputMap() {
            return this.inputMap;
        }


        public void setInputMap(HashMap<String, Object> inputMap) {
            this.inputMap = inputMap;
        }


        public HashMap<String, Object> getOutputMap() {
            return this.outputMap;
        }


        public void setOutputMap(HashMap<String, Object> outputMap) {
            this.outputMap = outputMap;
        }


        @Override
        public String toString() {
            return "Foo [inputMap=" + this.inputMap + ", outputMap=" + this.outputMap + "]";
        }

    }

}

и

@RunWith(SpringRunner.class)
@SpringBootTest
public class So55188061ApplicationTests {

    public final String sampleMessage =
                "{\"ORCH_KEY\":{\"inputMap\":{},"
            + "\"outputMap\":{\"activityId\":\"10001002\",\"activityStatus\":\"SUCCESS\"}}}";

    @Autowired
    private RabbitListenerEndpointRegistry registry;

    @Test
    public void test() throws Exception {
        AbstractMessageListenerContainer listenerContainer = (AbstractMessageListenerContainer) this.registry
                .getListenerContainer("foo");
        ChannelAwareMessageListener listener = (ChannelAwareMessageListener) listenerContainer.getMessageListener();
        Channel channel = mock(Channel.class);
        listener.onMessage(MessageBuilder.withBody(sampleMessage.getBytes())
                .andProperties(MessagePropertiesBuilder.newInstance()
                        .setContentType("application/json")
                        .setDeliveryTag(42L)
                        .build())
                .build(),
                channel);
        verify(channel).basicAck(42L, false);
    }

}

и

{ORCH_KEY=Foo [inputMap={}, outputMap={activityId=10001002, activityStatus=SUCCESS}]}
0 голосов
/ 15 марта 2019

В соответствии с вашим сложным требованием иметь все на борту, я не понимаю, как мы можем заключить сделку с mock(ConnectionFactory.class). Нам нужно было бы издеваться намного больше, чтобы все работало.

Вместо этого я бы предложил взглянуть на реальный интеграционный тест с существующим RabbitMQ или хотя бы встроенным QPid.

Кроме того, вы можете рассмотреть возможность использования @RabbitListenerTest до шпиона вашего @RabbitListener вызова без вмешательства в ваш производственный код.

Больше информации в Справочном руководстве: https://docs.spring.io/spring-amqp/docs/2.1.4.RELEASE/reference/#test-harness

...