3

如何模拟春季rabbitmq/amqp,以便在尝试自动创建交换/队列时在Spring Boot Test期间不会失败?如何在春季启动测试中模拟弹簧amqp /兔子

鉴于我有一个简单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引导检测过程中,像这样:

@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) 

在这个测试中,我不在乎兔子/ AMQP,那么我该如何嘲笑整个兔子/ AMQP呢?

回答

2

这不是特别容易,我们通常使用JUnit @Rule跳过测试,如果经纪人不可用。但是,我们确实有很多使用mock的测试,但您必须了解很多Spring AMQP内部使用它们的情况。您可以浏览project itself中的测试用例。

有一次,我确实尝试写一个模拟经纪人,但最终工作太多了。

+0

奇怪的是,它用于1.5.6 - 我只需要像这样配置一个Bean:Mockito.mock(AmqpTemplate.class) - 但现在1.6。1这不再工作:( – domi

+0

如果我是正确的,这也意味着我将无法使用任何SpringBoot测试用例与一个完整的容器,当我有这样的配置:( – domi

+0

嘲笑模板很容易;这是嘲弄经纪人的回应(确认,退货,交付),涉及更多,解释为“不再有效” - “AmqpTemplate”是一个简单的“界面”; 1.6中没有任何东西会改变它的嘲讽能力。对于'@ RabbitListener',你将不得不模拟一个监听器容器 –

1

我在某个时间点有类似的需求,看着QPid,它提供了一个内存AMQP代理。它迫使你保持在AMQP级别,并尽可能少使用rabbitMq特定代码。

但是我实际上找到了另一种方法:通过在运行测试+自动删除值时调整队列和交换的名称,我们不再存在这个问题。测试中的所有队列/交换名称后缀为(运行测试的帐户的)用户名,这意味着每个人都可以在其计算机上运行测试而不会影响其他人。

即使在我们的CI管道中,有些项目可能会使用相同的交换/队列:我们将测试中的值配置为项目特定的,这样即使两个项目同时在同一台机器上运行测试同一用户,消息不会在当前测试之外“泄漏”。

这最终比管理内存代理模拟或产生内存要简单得多。

1

不知道这是否有帮助,但我有同样的问题。所以,我只是在RabbitAdmin上使用了@MockBean,并使用了不同的配置文件,并且我没有得到相同的连接问题。测试通过。

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