Spring 5中的並發測試執行

1.簡介

JUnit 4開始,可以並行運行測試以提高大型套件的速度。問題是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.19.1</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.內幕

先前版本的框架不支持同時運行測試的主要原因是由於TestContextTestContextManager的管理。

Spring 5TestContextManager使用局部線程– 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並行運行測試的基本示例。

與往常一樣,示例代碼可以在Github上找到。