У меня настроены подписчик и издатель в bean-компоненте @Configuration, я хотел бы написать классы Junit для этих классов конфигурации с использованием макетов. При выполнении теста мне нужно загрузить эти bean-компоненты в контекст Spring, и я хотел бы смоделировать мой слушатель и соединение как фиктивный.
- Как смоделировать автоматические зависимости в классе Junit
- Как издеваться над аннотированным компонентом 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;
}
}
}