Spring 5中的並發測試執行
1.簡介
從JUnit 4
開始,可以並行運行測試以提高大型套件的速度。問題是Spring 5
之前的Spring TestContext Framework
不能完全支持並發測試執行。
在這篇快速文章中,我們將展示如何使用Spring 5
在Spring
項目中同時運行我們的測試。
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.內幕
先前版本的框架不支持同時運行測試的主要原因是由於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
並行運行測試的基本示例。
與往常一樣,示例代碼可以在Github上找到。