知識庫 / Spring RSS 訂閱

併發測試執行在 Spring 中

Spring,Testing
HongKong
4
02:39 PM · Dec 06 ,2025

1. 引言

JUnit 4 開始,測試可以並行運行以獲得更大套件的速度優勢。此前,由於 Spring TestContext Framework 不完全支持併發測試執行,因此併發測試執行存在問題。 Spring 5 之前,Spring TestContext Framework 對併發測試執行的支持不足。

在本文中,我們將演示如何使用 Spring 5Spring 項目中併發運行我們的測試。

2. Maven 設置

提醒一下,為了並行運行 JUnit 測試,我們需要配置 maven-surefire-plugin 以啓用該功能:

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

您可以在 參考文檔 中找到關於並行測試執行的更詳細配置信息。

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. 內部機制

先前版本的框架不支持併發運行測試的主要原因是由於 TestContext 的管理由 TestContextManager 負責。

Spring 5 中,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@FixMethodOrder
  • 修改 ApplicationContext,通常通過 @DirtiesContext 標記

5. 總結

在本快速教程中,我們演示了一個基本示例,使用 Spring 5 並行運行測試。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.