交換/キューを自動作成しようとしているときに、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全体をモックする方法を教えてください。
それほど簡単ではありません。ブローカーが利用できない場合は、通常、JUnit @Rule
を使用してテストをスキップします。
ただし、モックを使用する多くのテストがありますが、それらを使用するには、Spring AMQP内部の多くを実際に理解する必要があります。 プロジェクト自体 でテストケースを調べることができます。
ある時点で私はモックブローカーを書こうとしましたが、結局それはあまりにも多くの仕事になりました。
私はこれが古いトピックであることを知っていますが、私が開発しているモッキングライブラリを紹介したいと思います: 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
これが役立つことを願っています!
これが役立つかどうかはわかりませんが、同じ問題が発生していました。だから、私は@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
}
このプロジェクトでは、RabbitMQ
コンテナーをローカルで使用してdocker
インスタンスを初期化します。統合テストを実行するには、テストケースの最初にRabbitMQ
インスタンスを起動し、クリーンアップ中にシャットダウンします。
TestContainersを使用して、まさにそれを行っています。 https://www.testcontainers.org/usage/dockerfile.html および/または https://www.testcontainers.org/usage/docker_compose.html を参照してください。
ある時点で同様の要件があり、メモリ内AMQPブローカーを提供するQPidを調べました。 AMQPレベルを維持し、rabbitMq固有のコードをできるだけ使用しないようにする必要があります。
しかし、私は実際に別の方法を見つけました。テストの実行時にキューと交換の名前と自動削除の値を微調整することで、もう問題は発生していません。テスト内のすべてのキュー/交換名には、(テストを実行しているアカウントの)ユーザー名のサフィックスが付いています。つまり、誰もが他のユーザーに影響を与えることなく自分のマシンでテストを実行できます。
CIパイプラインでも、複数のプロジェクトが同じ交換/キューを使用する可能性があります。テストの値をプロジェクト固有に構成するため、2つのプロジェクトが同じユーザーの同じマシンで同時にテストを実行しても、メッセージ現在のテスト以外では「リーク」しません。
これは、インメモリブローカーのモックやスポーンよりも管理がはるかに簡単になります。
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 {
}
まず、@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 で見ています。