防止spring-rabbit中的@RabbitListener在集成测试期间尝试连接到服务器

时间:2017-07-05 13:03:13

标签: java spring rabbitmq spring-rabbit

我想为使用rabbitMq的服务运行一些验收测试,但我想忽略所有需要服务间通信(amqp)的服务。

然而问题是Spring尝试在启动时连接到(非现有的)Rabbit主机,以便它可以注册其消费者。它为每个使用@RabbitListener注释的方法执行此操作,如果我的服务中有多个侦听器,则会因长时间超时而烦恼。

如何减少此超时甚至阻止@RabbitListener连接?

我们的(简化)兔子配置:

@Configuration
@EnableRabbit
public class RabbitMqConfig {

    public RabbitMqConfig(
            @Value("${rabbitmq.host}") String rabbitHost,
            @Value("${rabbitmq.port}") int rabbitPort,
            @Value("${exchange.name}") String exchange) {
        this.rabbitHost = rabbitHost;
        this.rabbitPort = rabbitPort;
        this.exchange= exchange;
    }

  @Bean
  DirectExchange directExchangeBean() {
    return new DirectExchange(this.exchange, true, false);
  }

  @Bean
  public ConnectionFactory connectionFactory() {
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory(rabbitHost);
    connectionFactory.setPort(rabbitPort);
    return connectionFactory;
  }

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


  @Bean
  public Queue itemDoneQueue() {
    return new Queue(ITEM_DONE_QUEUENAME, true);
  }

  @Bean
  Binding itemDoneBinding() {
    return BindingBuilder.bind(itemDoneQueue()).to(directExchangeBean()).with(ITEM_DONE_KEY);
  }

}

属性

rabbitmq.host=192.168.42.100
rabbitmq.port=5672
exchange.name=myExchange

听众:

  @RabbitListener(queues = ITEM_DONE_QUEUENAME)
  public void receiveMessageFromItemDoneQueue(String message) {
    // do the work
  }

测试:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class}) 
public abstract class RabbitTest {

这里真的没什么特别的。显然,在测试期间,兔主机不可用。那样就好。我想忽略这个事实。很快。

我试过

spring.rabbitmq.connection-timeout=1

但这并没有改变任何事情。

使用

spring.rabbitmq.listener.simple.auto-startup=false

两者都没有。

使用

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

只是通过抱怨NoSuchBeanDefinitionException: No bean named 'rabbitListenerContainerFactory' available

的春天来杀死我的应用程序上下文加载

有什么想法吗? 谢谢!

5 个答案:

答案 0 :(得分:2)

我遇到了类似的问题,但是用

解决了

spring.rabbitmq.listener.direct.auto-startup=false

SpringBoot版本2.2.4.RELEASE

Spring框架版本5.2.3.RELEASE

答案 1 :(得分:1)

我希望children可以正常工作 - 你确定你没有尝试用其他代码连接到Rabbit吗?当设置为false时,您能提供DEBUG日志来显示问题吗?

您可以使用the JUnit BrokerRunning @Rule跳过任何需要真正RabbitMQ代理的测试。

答案 2 :(得分:1)

如果属性spring.rabbitmq.listener.simple.auto-startup=false无效,则您可能正在定义自己的SimpleRabbitListenerContainerFactory bean

检查如何在RabbitAnnotationDrivenConfiguration.rabbitListenerContainerFactory()

中定义此bean

SimpleRabbitListenerContainerFactoryConfigurerSimpleRabbitListenerContainerFactoryapplication.properties中定义的属性绑定在一起(除其他外)

如果使用自己的定义,请确保使用类似

的内容
@Bean
SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
    SimpleRabbitListenerContainerFactoryConfigurer containerFactoryConfigurer, 
    ConnectionFactory connectionFactory) {

    SimpleRabbitListenerContainerFactory listenerContainerFactory =
            new SimpleRabbitListenerContainerFactory();
    containerFactoryConfigurer.configure(listenerContainerFactory, connectionFactory);

    return listenerContainerFactory;
}

答案 3 :(得分:0)

感谢您的投入加里。 我已经找到了适合我的解决方案。由于某种原因,消费者初始化的连接超时未在我使用的CachingConnectionFactory中公开,也不是我尝试使用的属性(spring.rabbitmq.connection-timeout)。

我现在所做的是初始化基本ConnectionFactory并将其传递给CachingConnectionFactory(当然不知道差异在哪里,但大多数情况下都是春天的情况):

  @Bean
  public ConnectionFactory connectionFactory() {
    com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
    connectionFactory.setConnectionTimeout(this.connectionTimeout);
    connectionFactory.setHost(this.rabbitHost);
    connectionFactory.setPort(this.rabbitPort);
    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(
        connectionFactory);
    return cachingConnectionFactory;
  }

现在,我可以在接受测试期间将超时设置为1,从而导致消费者初始化快速失败并达到更高的部署值。

答案 4 :(得分:0)

您可以使用mockito模拟连接工厂,并添加BrokerRunning.isNotRunning()

的@Rule
@Bean
    ConnectionFactory connectionFactory() {
        ConnectionFactory factory = mock(ConnectionFactory.class);
        Connection connection = mock(Connection.class);
        Channel channel = mock(Channel.class);
        willReturn(connection).given(factory).createConnection();
        willReturn(channel).given(connection).createChannel(anyBoolean());
        given(channel.isOpen()).willReturn(true);
        return factory;
    }

这是您将添加到测试中的规则:

@Rule
public BrokerRunning brokerRunning = BrokerRunning.isNotRunning();