web-dev-qa-db-ja.com

春のブートテストで春のamqp / rabbitをモックする方法

交換/キューを自動作成しようとしているときに、Spring rabbitmq/amqpをモックしてSpring Boot Test中に失敗しないようにする方法は?

単純な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 Test中:

@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全体をモックする方法を教えてください。

12
domi

それほど簡単ではありません。ブローカーが利用できない場合は、通常、JUnit @Ruleを使用してテストをスキップします。

ただし、モックを使用する多くのテストがありますが、それらを使用するには、Spring AMQP内部の多くを実際に理解する必要があります。 プロジェクト自体 でテストケースを調べることができます。

ある時点で私はモックブローカーを書こうとしましたが、結局それはあまりにも多くの仕事になりました。

5
Gary Russell

私はこれが古いトピックであることを知っていますが、私が開発しているモッキングライブラリを紹介したいと思います: rabbitmq-mock

このモックの目的は、RabbitMQの動作をIO(サーバーを起動せずに、ポートをリッスンせずに)せずに)マイナー(〜なし)にして模倣することです。

Maven Centralで利用可能です:

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

基本的な使い方は、テスト構成でSpring構成をオーバーライドすることです。

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

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

テスト用のSpring Beanの自動モックについては、私が取り組んでいる別のプロジェクトを見てください: spring-automocker

これが役立つことを願っています!

10
Loïc Le Doyen

これが役立つかどうかはわかりませんが、同じ問題が発生していました。だから、私は@MockBean on 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
}
4
Rajkishan Swami

このプロジェクトでは、RabbitMQコンテナーをローカルで使用してdockerインスタンスを初期化します。統合テストを実行するには、テストケースの最初にRabbitMQインスタンスを起動し、クリーンアップ中にシャットダウンします。

TestContainersを使用して、まさにそれを行っています。 https://www.testcontainers.org/usage/dockerfile.html および/または https://www.testcontainers.org/usage/docker_compose.html を参照してください。

3
joy

ある時点で同様の要件があり、メモリ内AMQPブローカーを提供するQPidを調べました。 AMQPレベルを維持し、rabbitMq固有のコードをできるだけ使用しないようにする必要があります。

しかし、私は実際に別の方法を見つけました。テストの実行時にキューと交換の名前と自動削除の値を微調整することで、もう問題は発生していません。テスト内のすべてのキュー/交換名には、(テストを実行しているアカウントの)ユーザー名のサフィックスが付いています。つまり、誰もが他のユーザーに影響を与えることなく自分のマシンでテストを実行できます。

CIパイプラインでも、複数のプロジェクトが同じ交換/キューを使用する可能性があります。テストの値をプロジェクト固有に構成するため、2つのプロジェクトが同じユーザーの同じマシンで同時にテストを実行しても、メッセージ現在のテスト以外では「リーク」しません。

これは、インメモリブローカーのモックやスポーンよりも管理がはるかに簡単になります。

1
Vincent F

Rajkishanの回答 に多少似ていますが、私にとってはうまくいきませんでした。

これは代わりに私のために働いたものです:

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

}
1

まず、@Configuration with ConnectionFactory with your test package:

@Configuration
public class RabbitMqConfiguration {

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

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

}

その後、テストパッケージのapplication.ymlでこのプロパティを設定します。

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

これはSpring Boot 2.2.xで機能するはずです。

Spring Boot 1.5.xでは、もう1つの依存関係を追加する必要もありました。

<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 で見ています。

0
Dherik