Spring 5での同時テスト実行

1前書き

JUnit 4 から始めて、大規模スイートの速度を上げるためにテストを並行して実行することができます。問題は、並行テスト実行が、Spring 5以前のSpring TestContext Frameworkによって完全にはサポートされていなかったことです。

このクイック記事では、 Spring 5 を使用して Spring プロジェクトでテストを同時に実行する方法** を説明します。

2 Mavenのセットアップ

念のため、 JUnit テストを並行して実行するには、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.apache.maven.plugins%22%20ANDを設定する必要がありますこの機能を有効にするには、%20a%3A%22maven-surefire-plugin%22[ maven-surefire-plugin ]を使用してください。

<build>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.19.1</version>
        <configuration>
            <parallel>methods</parallel>
            <useUnlimitedThreads>true</useUnlimitedThreads>
        </configuration>
    </plugin>
</build>

並列テスト実行のより詳細な設定については、http://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html[参考資料]をご覧ください。

3同時テスト

次の例のテストは、Spring 5より前のバージョンで並行して実行すると失敗します。

ただし、 Spring 5 ではスムーズに動作します。

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Spring5JUnit4ConcurrentTest.SimpleConfiguration.class)
public class Spring5JUnit4ConcurrentTest implements ApplicationContextAware, InitializingBean {

    @Configuration
    public static class SimpleConfiguration {}

    private ApplicationContext applicationContext;

    private boolean beanInitialized = false;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.beanInitialized = true;
    }

    @Override
    public void setApplicationContext(
      final ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Test
    public void whenTestStarted__thenContextSet() throws Exception {
        TimeUnit.SECONDS.sleep(2);

        assertNotNull(
          "The application context should have been set due to ApplicationContextAware semantics.",
          this.applicationContext);
    }

    @Test
    public void whenTestStarted__thenBeanInitialized() throws Exception {
        TimeUnit.SECONDS.sleep(2);

        assertTrue(
          "This test bean should have been initialized due to InitializingBean semantics.",
          this.beanInitialized);
    }
}

連続して実行した場合、上記のテストに合格するまでに約6秒かかります。同時実行では、約4.5秒しかかかりません - これは、より大きなスイートでも節約できると期待できる時間の長さのために非常に一般的です。

4フードの下

以前のバージョンのフレームワークがテストの同時実行をサポートしていなかった主な理由は、 TestContextManager による TestContext の管理が原因でした。

Spring 5 では、http://docs.spring.io/spring/docs/5.0.0.M5/javadoc-api/org/springframework/test/context/TestContextManager.html[ TestContextManager ]はローカルスレッドを使用します - TestContext - 各スレッドの TestContexts に対する操作が妨げにならないようにするお互い。そのため、ほとんどのメソッドレベルおよびクラスレベルの同時テストでスレッドセーフが保証されています。

public class TestContextManager {

   //...
    private final TestContext testContext;

    private final ThreadLocal<TestContext> testContextHolder = new ThreadLocal<TestContext>() {
        protected TestContext initialValue() {
            return copyTestContext(TestContextManager.this.testContext);
        }
    };

    public final TestContext getTestContext() {
        return this.testContextHolder.get();
    }

   //...
}

並行処理サポートはすべての種類のテストには適用されないことに注意してください。 テストを除外する必要があります :

  • キャッシュ、データベース内の状態などの外部共有状態を変更します。

メッセージキューなど

  • 特定の実行順序が必要

JUnit ´s @FixMethodOrder ** で示される ApplicationContext を変更します。

5概要

このクイックチュートリアルでは、 Spring 5 を使用してテストを並行して実行する基本的な例を示しました。

いつものように、サンプルコードはhttps://github.com/eugenp/tutorials/tree/master/spring-5/src/test/java/com/baeldung[Githubに追加]を見つけることができます。