Search code examples
junitrabbitmqspring-amqptestcontainers

why the test container with the RabbitMQ is creates every time anew and is not shared between the tests


I have 4 tests for listeners, the application is built on SpringBoot and uses Testcontainers, I run mvn clean install, and I get the following:

9-08-15 18:37:01.287  INFO 8312 --- [tContainer#1-11] o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [localhost:33724]
[INFO] 
[INFO] Results:
[INFO] 
2019-08-15 18:37:01.288 ERROR 8312 --- [tContainer#1-11] o.s.a.r.l.SimpleMessageListenerContainer : Failed to check/redeclare auto-delete queue(s).

org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused (Connection refused)
    at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:62)
    at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:509)
    at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:682)
    at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.createConnection(ConnectionFactoryUtils.java:214)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:2073)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2047)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2027)
    at org.springframework.amqp.rabbit.core.RabbitAdmin.getQueueProperties(RabbitAdmin.java:403)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.attemptDeclarations(AbstractMessageListenerContainer.java:1787)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.redeclareElementsIfNecessary(AbstractMessageListenerContainer.java:1768)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.initialize(SimpleMessageListenerContainer.java:1195)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1041)
    at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: java.net.ConnectException: Connection refused (Connection refused)
    at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
    at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
    at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
    at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)
    at java.base/java.net.Socket.connect(Socket.java:591)
    at com.rabbitmq.client.impl.SocketFrameHandlerFactory.create(SocketFrameHandlerFactory.java:60)
    at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1102)
    at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1054)
    at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:994)
    at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:462)
    ... 11 common frames omitted

I made an output to the log file of the mvn clean install command, and the above occurs throughout the entire log, many times, but this is not the main problem, the problem is that the container with RabbitMQ starts many times, I would like to share it between tests.

2019-08-15 18:35:26.126  INFO   --- [           main] 🐳 [rabbitmq:3.7-management]             : Creating container for image: rabbitmq:3.7-management

2019-08-15 18:35:54.665  INFO 8312 --- [           main] 🐳 [rabbitmq:3.7-management]             : Creating container for image: rabbitmq:3.7-management

2019-08-15 18:36:15.510  INFO 8312 --- [           main] 🐳 [rabbitmq:3.7-management]             : Creating container for image: rabbitmq:3.7-management

2019-08-15 18:36:31.862  INFO 8312 --- [           main] 🐳 [rabbitmq:3.7-management]             : Creating container for image: rabbitmq:3.7-management

4 times, 4 listeners.

I tried using forkCount = 0 for maven-surefire-plugin and for maven-failsafe-plugin, this did not help.

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M3</version>
                <configuration>
                    <forkCount>0</forkCount>
                </configuration>
            </plugin>

@RunWith(SpringRunner.class)
@SpringBootTest(
        value = {
                "spring.cloud.discovery.enabled = false"
        },
        webEnvironment = RANDOM_PORT)
@ActiveProfiles(TEST_PROFILE)
public abstract class AbstractTest {

    @LocalServerPort
    private int port;

}
@ContextConfiguration(initializers = AbstractRabbitTest.Initializer.class)
public abstract class AbstractRabbitTest extends AbstractTest {
    @ClassRule
    public static RabbitMQContainer rabbitMQContainer = new RabbitMQContainer("rabbitmq:3.7-management")
            .withExposedPorts(5672)
            .withVhost("/")
            .withUser("admin", "admin")
            .withPermission("/", "admin", ".*", ".*", ".*");

    public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
            TestPropertyValues values = TestPropertyValues.of(
                    "spring.rabbitmq.host=" + rabbitMQContainer.getContainerIpAddress(),
                    "spring.rabbitmq.port=" + rabbitMQContainer.getMappedPort(5672),
                    "spring.rabbitmq.username=admin",
                    "spring.rabbitmq.password=admin"
            );
            values.applyTo(applicationContext);
        }
    }
}

Every my test looks like this and uses spring-amqp:

public class CloseProcessListenerTest extends AbstractRabbitTest {

Solution

  • ClassRule in JUnit will execute the rule per class, not per "suite". Since you have multiple test classes that extend it, you start multiple containers during the tests.

    Consider using the Singleton Container pattern and check Spring Boot example