web-dev-qa-db-fra.com

comment se moquer du printemps amqp/lapin dans le test de démarrage du printemps

Comment se moquer de spring rabbitmq/amqp pour ne pas échouer lors d'un test de démarrage de printemps lors de la tentative de création automatique d'échanges/de files d'attente?

Étant donné que j’ai une simple RabbitListener qui créera automatiquement la file et l’échange de la manière suivante:

@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) {
      ...
    }   
}

Pendant un simple test de démarrage du printemps, comme ceci:

@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = { Application.class })

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void test() {
        assertNotNull(applicationContext);
    }

}

il échouera avec:

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)

Dans ce test, je me fiche de Lapin/AMQP, alors comment puis-je me moquer de tout le Lapin/AMQP?

6
domi

Ce n'est pas particulièrement facile, nous utilisons généralement un JUnit @Rule pour ignorer le test si le courtier n'est pas disponible.

Cependant, nous avons beaucoup de tests qui utilisent des simulacres, mais vous devez vraiment comprendre une bonne partie des internes de Spring AMQP pour pouvoir les utiliser. Vous pouvez explorer les cas de test dans le projet lui-même .

À un moment donné, j’ai tenté d’écrire un faux courtier, mais c’était trop de travail.

5
Gary Russell

Je sais que c'est un vieux sujet, mais j'aimerais vous présenter une bibliothèque moqueuse que je développe: rabbitmq-mock .

Le but de cette simulation est d’imiter le comportement de RabbitMQ sans IO (sans démarrer un serveur, écouter de port, etc.) et avec un temps de démarrage mineur (~ aucun).

Il est disponible dans Maven Central:

<dependency>
    <groupId>com.github.fridujo</groupId>
    <artifactId>rabbitmq-mock</artifactId>
    <version>1.0.9</version>
    <scope>test</scope>
</dependency>

L’utilisation de base consistera à remplacer la configuration de Spring par un test:

@Configuration
@Import(AmqpApplication.class)
class AmqpApplicationTestConfiguration {

    @Bean
    public ConnectionFactory connectionFactory() {
        return new CachingConnectionFactory(MockConnectionFactoryFactory.build());
    }
}

Pour vous moquer automatiquement des haricots du printemps à des fins de test, jetez un œil à un autre projet sur lequel je travaille: spring-automocker

J'espère que cela peut aider!

7
Loïc Le Doyen

Je ne suis pas sûr que cela soit utile, mais j'avais le même problème. Donc, je viens d'utiliser @MockBean sur RabbitAdmin avec un profil différent, et je n'ai pas eu les mêmes problèmes de connexion. Tests réussis.

@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
}
3
Raj

Dans notre projet, nous initialisons une instance RabbitMQ à l'aide d'un conteneur docker localement. Pour exécuter un test d'intégration, nous activons une instance RabbitMQ au début du scénario de test et nous la fermons pendant le nettoyage.

Nous utilisons TestContainers pour faire exactement cela. Veuillez consulter https://www.testcontainers.org/usage/dockerfile.html et/ou https://www.testcontainers.org/usage/docker_compose.html .

2
joy

J'avais une exigence similaire à un moment donné et j'ai examiné QPid, qui fournit un courtier AMQP en mémoire. Cela vous oblige à rester au niveau AMQP et à utiliser le moins possible de code spécifique à RabbitMq. 

Mais j’ai en fait trouvé une autre solution: en modifiant les noms des files d’attente et des échanges lors de l’exécution de tests + de la valeur de suppression automatique, le problème ne se pose plus. Tous les noms de file d'attente/d'échange dans les tests sont suffixés du nom d'utilisateur (du compte qui exécute les tests), ce qui signifie que tout le monde peut exécuter les tests sur sa machine sans en affecter les autres. 

Même dans notre pipeline CI, plusieurs projets peuvent utiliser les mêmes échanges/files d'attente: nous configurons les valeurs dans les tests de manière à ce qu'ils soient spécifiques au projet. Ainsi, même si 2 projets exécutent leurs tests en même temps sur le même ordinateur avec le même utilisateur, des messages sont envoyés. ne "coulera" pas en dehors du test en cours. 

Cela finit par être beaucoup plus simple à gérer que de se moquer ou de générer un courtier en mémoire. 

1
Vincent F