如何在 Spring Boot 测试中模拟Springamqp/rabbit

wqlqzqxt  于 2023-02-07  发布在  Spring
关注(0)|答案(8)|浏览(143)

如何模拟spring rabbitmq/amqp,使其在尝试自动创建交换/队列时不会在Sping Boot 测试期间失败?
假设我有一个简单的RabbitListener,它将导致队列和交换自动创建,如下所示:

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

在简单的 Spring Boot 测试期间,如下所示:

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

    @Autowired
    private ApplicationContext applicationContext;

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

}

它将失败:

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)

在这个测试中,我不关心Rabbit/AMQP,所以我怎么能嘲笑整个Rabbit/AMQP呢?

nimxete2

nimxete21#

我知道这是一个老主题,但是我想介绍一下我正在开发的一个模拟库:rabbitmq-mock.
这个模拟的目的是模拟RabbitMQ的行为,没有IO(没有启动服务器,监听一些端口,等等),启动时间很短(~没有)。
它可在Maven Central获得:

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

基本用途是用测试配置覆盖Spring配置:

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

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

为了自动模拟Springbean进行测试,看看我正在做的另一个项目:spring-automocker
希望这能有所帮助!

shyt4zoc

shyt4zoc2#

不确定这是否有帮助,但是,我也遇到了同样的问题。所以,我只是在RabbitAdmin上使用了不同的配置文件,没有遇到同样的连接问题。测试通过。

@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
}
xmq68pz9

xmq68pz93#

这并不特别容易,如果代理不可用,我们通常使用JUnit @Rule跳过测试。
然而,我们确实有很多使用模拟的测试,但是你真的需要了解很多Spring AMQP的内部机制才能使用它们,你可以在project itself中探索测试用例。
有一次我确实尝试过编写一个模拟经纪人,但最终工作量太大。

yfwxisqw

yfwxisqw4#

在我们的项目中,我们在本地使用docker容器初始化一个RabbitMQ示例,为了运行集成测试,我们在测试用例开始时启动一个RabbitMQ示例,并在清理过程中关闭它。
我们正在使用TestContainers来实现这一点。请参阅https://www.testcontainers.org/usage/dockerfile.html和/或https://www.testcontainers.org/usage/docker_compose.html

knpiaxh1

knpiaxh15#

有点类似于Rajkishan's answer,但对我不起作用:
这是对我起作用的:

@SpringBootApplication
public class MyTestsApp {
    @Bean
    @Primary
    public CachingConnectionFactory rabbitAdmin() {
        return Mockito.mock(CachingConnectionFactory.class);
    }
}

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MyTestsApp.class})
@ActiveProfiles(profiles = "test")
public class MyTests {

}
lvmkulzt

lvmkulzt6#

我在某个时候也有类似的需求,我研究了QPid,它提供了一个内存中的AMQP代理,它迫使你停留在AMQP级别,并尽可能少地使用rabbitMq特定的代码。
但我找到了另一种方法:通过在运行测试时调整队列和交换机的名称+自动删除值,我们不再有这个问题了。测试中的所有队列/交换机名称都以用户名作为后缀(运行测试的帐户),这意味着每个人都可以在自己的机器上运行测试而不会影响其他人。
即使在我们的CI管道中,多个项目也可能使用相同的交换/队列:我们将测试中的值配置为特定于项目,这样即使两个项目在同一台机器上使用同一个用户同时运行它们的测试,消息也不会“泄漏”到当前测试之外。
这比模拟或生成内存中的代理要简单得多。

bqucvtff

bqucvtff7#

首先,在测试包中创建一个@Configuration

@Configuration
public class RabbitMqConfiguration {

    @Bean
    ConnectionFactory connectionFactory() {
        return new CachingConnectionFactory();
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
       return new RabbitTemplate(connectionFactory);
    }

}

然后,在测试包中的应用程序.yml中设置此属性:

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration

这应该适用于Sping Boot 2.2.x。
对于Sping Boot 1.5.x,我还需要添加一个依赖项:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-test-support</artifactId>
    <scope>test</scope>
</dependency>

我不知道为什么,但是没有spring-cloud-stream-test-support依赖项,我的集成测试尝试连接RabbitMQ代理。即使不影响测试本身的结果,这在每个测试中占用了很多秒。我已经在another post中看到了这种奇怪的行为。

ncecgwcz

ncecgwcz8#

您还可以指定要启用监听程序的概要文件。例如,我们可以为测试设置test概要文件

@SpringBootTest
@ActiveProfiles("test")
class SomeTests {
}

并禁用Rabbit监听器的配置文件

@Service
@Profile("!test")
public class MyMessagesConsumer {

  @RabbitListener
  public void listenToMessage(String msg) {
     // ...
  }
}

相关问题