简体   繁体   中英

Connect to message broker with Spring cloud stream from test

There are articles on how to test Spring cloud stream applications without connecting to a messaging system with spring-cloud-stream-test-support. But I want to really connect to RabbitMQ from my integration test, and cannot do that. Here is test class:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableBinding(Source.class)
public class StreamIT {

  @Autowired
  private Source source;

  @Test
  public void testMessageSending() throws InterruptedException {
    source.output().send(MessageBuilder.withPayload("test").build());
    System.out.println("Message sent.");
  }

}

Everything is the same as in @SpringBootApplication, they use the same properties from application.yml.

But there is no log line that message is sent ( osarcCachingConnectionFactory : Created new connection: SpringAMQP#22e79d25:0/SimpleConnection@5cce3ab6 [delegate=amqp://guest@127.0.1.1:5672/, localPort= 60934] ), and even if broker is not started, there is no java.net.ConnectException: Connection refused (Connection refused) .

Am I doing something wrong? What is needed to create real connection to broker and send message from test?

EDIT

You need to remove the test-support jar from the pom. It's presence (in test scope) is what triggers replacing the real binder with a test binder.

After removing the test binder support, this works fine for me...

@RunWith(SpringRunner.class)
@SpringBootTest
public class So49816044ApplicationTests {

    @Autowired
    private Source source;

    @Autowired
    private AmqpAdmin admin;

    @Autowired
    private RabbitTemplate template;

    @Test
    public void test() {
        // bind an autodelete queue to the destination exchange
        Queue queue = this.admin.declareQueue();
        this.admin.declareBinding(new Binding(queue.getName(), DestinationType.QUEUE, "mydest", "#", null));

        this.source.output().send(new GenericMessage<>("foo"));

        this.template.setReceiveTimeout(10_000);
        Message received = template.receive(queue.getName());
        assertThat(received.getBody()).isEqualTo("foo".getBytes());
    }

}

Although there is not a rabbit sample; there is a kafka sample that uses a real (embedded) kafka binder for testing , although the test jar is excluded, it doesn't explicitly say that's needed.

Since you are using @SpringBootTest annotation in your test, Spring Boot will evaluate all available auto-configurations.

If you have spring-cloud-stream-test-support dependency in your test classpath then following auto-configurations will be also evaluated:

  • org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration
  • org.springframework.cloud.stream.test.binder.MessageCollectorAutoConfiguration

As a result, you have only one binder in the application context - org.springframework.cloud.stream.test.binder.TestSupportBinder . By its name, you can understand that it does nothing about real binding.

Excluding/removing of spring-cloud-stream-test-support dependency from test classpath - is a dubious solution. Since it forces you to create two separate modules for unit and integration tests.

If you want to exclude previously mentioned auto-configurations in your test. You can do it as follows:

@RunWith(SpringRunner.class)
@SpringBootTest
@EnableAutoConfiguration(exclude = {TestSupportBinderAutoConfiguration.class, MessageCollectorAutoConfiguration.class})
public class StreamIT {

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM