How to mock spring rabbitmq/amqp so it will not fail during a Spring Boot Test while trying to auto create exchanges/queues?
Given I have a simple RabbitListener
that will cause the queue and exchange to be auto created like this:
@Component @RabbitListener(bindings = { @QueueBinding( value = @Queue(value = "myqueue", autoDelete = "true"), exchange = @Exchange(value = "myexchange", autoDelete = "true", type = "direct"), key = "mykey")} ) @RabbitListenerCondition public class EventHandler { @RabbitHandler public void onEvent(Event event) { ... } }
During a simple Spring Boot Test, like this:
@ActiveProfiles("test") @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = { Application.class }) @Autowired private ApplicationContext applicationContext; @Test public void test() { assertNotNull(applicationContext); } }
it will fail with:
16:22:16.527 [SimpleAsyncTaskExecutor-1] ERROR o.s.a.r.l.SimpleMessageListenerContainer - Failed to check/redeclare auto-delete queue(s). org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:62) at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:309)
In in this test I don't care about Rabbit/AMQP, so how can I mock the whole Rabbit/AMQP away?
To achieve this, we can use the mocking support provided by Spring Boot Test. To check the Service class, we need to have an instance of the Service class created and available as a @Bean so that we can @Autowire it in our test class. We can achieve this configuration using the @TestConfiguration annotation.
In order to test that our Listener is capable of consuming the messages, first we must send a test message. . . . @Autowired private lateinit var rabbitTemplate: RabbitTemplate @Autowired private lateinit var rabbitAdmin: RabbitAdmin @Before fun setUp() { rabbitAdmin.
Briefly, AMQP is made up of Exchanges, Queues, and Bindings: Exchanges are like post offices or mailboxes and clients publish a message to an AMQP exchange. There are four built-in exchange types. Direct Exchange – Routes messages to a queue by matching a complete routing key.
RabbitMQ is a common messaging broker which allows applications to connect and communicate. It's common for services in microservices-based systems to communicate asynchronously through messaging. In order to create such a message-based system, you need a message broker, aka messaging server.
I know this is an old topic, but I'd like to introduce a mocking library I'm developping : rabbitmq-mock.
The purpose of this mock is to mimic RabbitMQ behavior without IO (without starting a server, listening to some port, etc.) and with minor (~ none) startup time.
It is available in Maven Central:
<dependency> <groupId>com.github.fridujo</groupId> <artifactId>rabbitmq-mock</artifactId> <version>1.1.1</version> <scope>test</scope> </dependency>
Basic use will be to override Spring configuration with a test one :
@Configuration @Import(AmqpApplication.class) class AmqpApplicationTestConfiguration { @Bean public ConnectionFactory connectionFactory() { return new CachingConnectionFactory(MockConnectionFactoryFactory.build()); } }
For automatic mocking of Spring beans for tests, give a look at another project I'm working on: spring-automocker
Hope this can help !
Not sure if this is helpful but, I was having the same problem. So, I just used @MockBean
on RabbitAdmin
with a different profile, and did not get the same connection issues. Tests Passed.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @RunWith(SpringRunner.class) @ActiveProfiles("my-test") public class ServiceTests { @Autowired private DummyService unitUnderTest; @MockBean private RabbitAdmin rabbitAdmin; // lots of tests which do not need Spring to Create a RabbitAdmin Bean }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With