RabbitListenerTestHarness 在侦听器中注入实际对象
RabbitListenerTestHarness injects actual objects in listeners
场景:
微服务的 Junit,它在数据提取后监听队列和 posts 到 rabbitMQ 中的交换。
问题:
RabbitListenerTestHarness is creating mock object for the Rabbit
Listener class alone, Actual objects are being instantiated for
Listeners Autowired components
我找不到手动将模拟 bean 注入侦听器的方法。这会导致 Junit post 在 Junit 执行期间将测试消息发送到微服务中配置的实际队列。
解决方法: 我可以使用 rabbit-test 项目的唯一方法是在 Junit 执行期间为 posting 消息配置测试交换。
查询:
我想了解,是否有更好的方式为 Rabbit Listener 编写 Junit。此外,我想了解是否有一种方法可以将模拟对象手动注入 Rabbit Listeners 自动装配组件。
示例代码片段:
兔子听众Class
@RabbitListener(id = "id", bindings = @QueueBinding(value = @Queue(value = "sampleQueue", durable = "true", autoDelete = "false"),key = "sampleRoutingKey", exchange = @Exchange(value = "sampleExchange", durable = "true", ignoreDeclarationExceptions = "true", type = EXCHANGE_TYPE)))
public void getMessageFromQueue(@Payload EventModel event) throws ListenerExecutionFailedException, JAXBException {
dataExporterService.exportDataAndPostToRabbit(event);
}
服务class
@Autowired
DataExtractorRepository dataExtractorRepository;
@Autowired
DataPublihserRepository dataPublisherRepo;
public void exportDataAndPostToRabbit(EventModel event) throws JAXBException {
dataPublisherRepo.sendMessageToExchange(dataExtractorRepository.extractOrderData(event), exchangeName, routingKeyValue);
}
DataPublihserRepository 在内部自动装配了 rabbitTemplate。 DataExtractorRepository 在内部连接到 DB 以检索消息。
测试class
@Autowired
private RabbitListenerTestHarness harness;
@Autowired
private RabbitTemplate rabbitTemplate;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
DataExporterController = this.harness.getSpy("id");
}
@Test
public void shouldReceiveMessage() throws Exception {
LatchCountDownAndCallRealMethodAnswer answer = new LatchCountDownAndCallRealMethodAnswer(1);
doAnswer(answer).when(DataExporterController).getMessageFromQueue(any(EventModel.class));
rabbitTemplate.convertAndSend("sampleExchange", "sampleRoutingKey", createMessage());
assertTrue(answer.getLatch().await(10, TimeUnit.SECONDS));
verify(DataExporterController, times(1)).getMessageFromQueue(any(OrderEventsModel.class));
verify(orderDataExporterController, times(1)).getMessageFromQueue(any(OrderEventsModel.class));
}
private Message createMessage() {
String inputObject = "{\"id\":12345}";
MessageProperties props = MessagePropertiesBuilder.newInstance().setContentType(MessageProperties.CONTENT_TYPE_JSON).build();
return new Message(inputObject.getBytes(), props);
}
线束旨在作为一种机制来验证侦听器是否在集成测试中接收到数据。要对侦听器进行单元测试,请调用其 onMessage
方法。
例如使用Mockito,给定
public class MyListener {
@Autowired
private SomeService service;
@RabbitListener(id = "myListener", queues = "foo")
public void listen(Foo foo) {
this.service.process(foo);
}
}
和
public interface SomeService {
void process(Foo foo);
}
然后
@RunWith(SpringRunner.class)
public class So53136882ApplicationTests {
@Autowired
private RabbitListenerEndpointRegistry registry;
@Autowired
private SomeService service;
@Test
public void test() throws Exception {
SimpleMessageListenerContainer container = (SimpleMessageListenerContainer) this.registry
.getListenerContainer("myListener");
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
Message message = MessageBuilder.withBody("{\"bar\":\"baz\"}".getBytes())
.andProperties(MessagePropertiesBuilder.newInstance()
.setContentType("application/json")
.build())
.build();
listener.onMessage(message, mock(Channel.class));
verify(this.service).process(new Foo("baz"));
}
@Configuration
@EnableRabbit
public static class config {
@Bean
public ConnectionFactory mockCf() {
return mock(ConnectionFactory.class);
}
@Bean
public MessageConverter converter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(mockCf());
factory.setMessageConverter(converter());
factory.setAutoStartup(false);
return factory;
}
@Bean
public MyListener myListener() {
return new MyListener();
}
@Bean
public SomeService service() {
return mock(SomeService.class);
}
}
}
请注意,容器工厂不会启动侦听器容器。
为了测试发布,注入一个由 RabbitTemplate
实现的模拟 RabbitOperations
。
例如给定
public class SomeServiceImpl implements SomeService {
@Autowired
private RabbitOperations rabbitOperations;
@Override
public void process(Foo foo) {
this.rabbitOperations.convertAndSend(
"someExchange", "someRoutingKey", new Foo(foo.getBar().toUpperCase()));
}
}
和
@Bean
public SomeService service() {
return new SomeServiceImpl();
}
@Bean
public RabbitOperations rabbitTemplate() {
return mock(RabbitOperations.class);
}
然后
@Test
public void test() throws Exception {
SimpleMessageListenerContainer container = (SimpleMessageListenerContainer) this.registry
.getListenerContainer("myListener");
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
Message message = MessageBuilder.withBody("{\"bar\":\"baz\"}".getBytes())
.andProperties(MessagePropertiesBuilder.newInstance()
.setContentType("application/json")
.build())
.build();
listener.onMessage(message, mock(Channel.class));
verify(this.rabbitTemplate).convertAndSend("someExchange", "someRoutingKey", new Foo("BAZ"));
}
场景: 微服务的 Junit,它在数据提取后监听队列和 posts 到 rabbitMQ 中的交换。
问题:
RabbitListenerTestHarness is creating mock object for the Rabbit Listener class alone, Actual objects are being instantiated for Listeners Autowired components
我找不到手动将模拟 bean 注入侦听器的方法。这会导致 Junit post 在 Junit 执行期间将测试消息发送到微服务中配置的实际队列。
解决方法: 我可以使用 rabbit-test 项目的唯一方法是在 Junit 执行期间为 posting 消息配置测试交换。
查询: 我想了解,是否有更好的方式为 Rabbit Listener 编写 Junit。此外,我想了解是否有一种方法可以将模拟对象手动注入 Rabbit Listeners 自动装配组件。
示例代码片段:
兔子听众Class
@RabbitListener(id = "id", bindings = @QueueBinding(value = @Queue(value = "sampleQueue", durable = "true", autoDelete = "false"),key = "sampleRoutingKey", exchange = @Exchange(value = "sampleExchange", durable = "true", ignoreDeclarationExceptions = "true", type = EXCHANGE_TYPE)))
public void getMessageFromQueue(@Payload EventModel event) throws ListenerExecutionFailedException, JAXBException {
dataExporterService.exportDataAndPostToRabbit(event);
}
服务class
@Autowired
DataExtractorRepository dataExtractorRepository;
@Autowired
DataPublihserRepository dataPublisherRepo;
public void exportDataAndPostToRabbit(EventModel event) throws JAXBException {
dataPublisherRepo.sendMessageToExchange(dataExtractorRepository.extractOrderData(event), exchangeName, routingKeyValue);
}
DataPublihserRepository 在内部自动装配了 rabbitTemplate。 DataExtractorRepository 在内部连接到 DB 以检索消息。
测试class
@Autowired
private RabbitListenerTestHarness harness;
@Autowired
private RabbitTemplate rabbitTemplate;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
DataExporterController = this.harness.getSpy("id");
}
@Test
public void shouldReceiveMessage() throws Exception {
LatchCountDownAndCallRealMethodAnswer answer = new LatchCountDownAndCallRealMethodAnswer(1);
doAnswer(answer).when(DataExporterController).getMessageFromQueue(any(EventModel.class));
rabbitTemplate.convertAndSend("sampleExchange", "sampleRoutingKey", createMessage());
assertTrue(answer.getLatch().await(10, TimeUnit.SECONDS));
verify(DataExporterController, times(1)).getMessageFromQueue(any(OrderEventsModel.class));
verify(orderDataExporterController, times(1)).getMessageFromQueue(any(OrderEventsModel.class));
}
private Message createMessage() {
String inputObject = "{\"id\":12345}";
MessageProperties props = MessagePropertiesBuilder.newInstance().setContentType(MessageProperties.CONTENT_TYPE_JSON).build();
return new Message(inputObject.getBytes(), props);
}
线束旨在作为一种机制来验证侦听器是否在集成测试中接收到数据。要对侦听器进行单元测试,请调用其 onMessage
方法。
例如使用Mockito,给定
public class MyListener {
@Autowired
private SomeService service;
@RabbitListener(id = "myListener", queues = "foo")
public void listen(Foo foo) {
this.service.process(foo);
}
}
和
public interface SomeService {
void process(Foo foo);
}
然后
@RunWith(SpringRunner.class)
public class So53136882ApplicationTests {
@Autowired
private RabbitListenerEndpointRegistry registry;
@Autowired
private SomeService service;
@Test
public void test() throws Exception {
SimpleMessageListenerContainer container = (SimpleMessageListenerContainer) this.registry
.getListenerContainer("myListener");
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
Message message = MessageBuilder.withBody("{\"bar\":\"baz\"}".getBytes())
.andProperties(MessagePropertiesBuilder.newInstance()
.setContentType("application/json")
.build())
.build();
listener.onMessage(message, mock(Channel.class));
verify(this.service).process(new Foo("baz"));
}
@Configuration
@EnableRabbit
public static class config {
@Bean
public ConnectionFactory mockCf() {
return mock(ConnectionFactory.class);
}
@Bean
public MessageConverter converter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(mockCf());
factory.setMessageConverter(converter());
factory.setAutoStartup(false);
return factory;
}
@Bean
public MyListener myListener() {
return new MyListener();
}
@Bean
public SomeService service() {
return mock(SomeService.class);
}
}
}
请注意,容器工厂不会启动侦听器容器。
为了测试发布,注入一个由 RabbitTemplate
实现的模拟 RabbitOperations
。
例如给定
public class SomeServiceImpl implements SomeService {
@Autowired
private RabbitOperations rabbitOperations;
@Override
public void process(Foo foo) {
this.rabbitOperations.convertAndSend(
"someExchange", "someRoutingKey", new Foo(foo.getBar().toUpperCase()));
}
}
和
@Bean
public SomeService service() {
return new SomeServiceImpl();
}
@Bean
public RabbitOperations rabbitTemplate() {
return mock(RabbitOperations.class);
}
然后
@Test
public void test() throws Exception {
SimpleMessageListenerContainer container = (SimpleMessageListenerContainer) this.registry
.getListenerContainer("myListener");
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
Message message = MessageBuilder.withBody("{\"bar\":\"baz\"}".getBytes())
.andProperties(MessagePropertiesBuilder.newInstance()
.setContentType("application/json")
.build())
.build();
listener.onMessage(message, mock(Channel.class));
verify(this.rabbitTemplate).convertAndSend("someExchange", "someRoutingKey", new Foo("BAZ"));
}