web-dev-qa-db-ja.com

Springブートテストですでに使用されているポートの解決DEFINED PORT

Application Ready eventをリッスンしてクラスを起動および実行するSpring Bootアプリケーションがあり、external serviceを呼び出して一部のデータをフェッチし、そのデータを使用して一部をプッシュします実行するクラスパスへのルール。ローカルテストの場合、アプリケーション内に外部サービスのモックがあり、アプリケーションの起動時に正常に機能します。

問題はテスト中ですアプリケーションをスプリングブートテストアノテーションを付けて実行し、次のいずれかで突堤コンテナを埋め込みます:

  • ランダムポート
  • DEFINED PORT

RANDOM PORTの場合、アプリケーションの起動時に、定義されたポートのプロパティファイルからモックサービスのURLを取得し、手掛かりはありません埋め込まれたコンテナーがランダムに取得されるため実行されているため、応答を返すことができません。

DEFINED PORTの場合、最初のテストケースファイルは正常に実行されますが、次のファイルが取得された瞬間に、ポートはすでに使用中で。

テストケースは複数のファイルに論理的に分割されており、コンテナーがルールの読み込みを開始する前に外部サービスを呼び出す必要があります。

定義済みのポートを使用している場合にテストファイル間で埋め込みコンテナーを共有するか、テストケースの実行中に起動するときにランダムなポートを取得するためにアプリケーションコードをリファクタリングするにはどうすればよいですか?.

任意の助けいただければ幸いです。

アプリケーションスタートアップコード:

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

@Autowired
private SomeService someService;

@Override
public void onApplicationEvent(ApplicationReadyEvent arg0) {

    try {
        someService.callExternalServiceAndLoadData();
    }
    catch (Execption e) {}
    }
 }

テストコードアノテーション:Test1

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test1 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}

テストコードアノテーション:Test2

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test2 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}
13
ahj.ashish

私は同じ問題に出くわしました。私はこの質問が少し古いことを知っていますが、これは助けになるかもしれません:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)を使用するテストでは、次の例に示すように、@ LocalServerPortアノテーションを使用して実際のポートをフィールドに挿入することもできます。

ソース: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-user-a-random-unassigned-http-port

与えられたコード例は次のとおりです:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {

    @Autowired
    ServletWebServerApplicationContext server;

    @LocalServerPort
    int port;

    // ...

}
3
cbreezier

複数のテストで同じポートを使用するように主張する場合は、次のようにテストクラスに注釈を付けることにより、Springが後続のテストのコンテキストをキャッシュしないようにすることができます。@DirtiesContext

あなたの場合:

@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")

これは、 このディスカッション に関する彼の回答からのアンディ・ウィルキンソンの引用です

これは設計どおりに機能しています。 Spring Frameworkのテストフレームワークは、デフォルトで、複数のテストクラスで再利用できるようにコンテキストをキャッシュします。 (@TestPropertySourceにより)構成が異なる2つのテストがあるため、異なるアプリケーションコンテキストを使用します。最初のテストのコンテキストはキャッシュされ、2番目のテストの実行中は開いたままになります。どちらのテストも、Tomcatのコネクタに同じポートを使用するように構成されています。その結果、2番目のテストが実行されると、最初のテストのコネクタとのポートの衝突により、コンテキストの開始に失敗します。いくつかのオプションがあります:

  1. RANDOM_PORTを使用
  2. @TestPropertySourceをTest2から削除して、コンテキストが同じ構成になり、最初のテストのコンテキストを2番目のテストで再利用できるようにします。
  3. @DirtiesContextを使用して、コンテキストがキャッシュされないようにします
2
Joel Neukom