Spring Boot测试类重复重启重建ApplicationContext,如何高效批量运行测试?
Maven Surefire插件配置:
<includes> <include>**/*Test*.java</include> </includes>
基类代码:
@AutoConfigureMockMvc @SpringBootTest @ActiveProfiles("test") public class ApplicationTests { }
所有测试类均继承该基类,测试类通常结构如下:
@ExtendsWith(SpringExtension.class) public class ATestClass extends ApplicationTests { @Test // 测试方法 }
执行mvn clean package命令时,所有测试均可正常运行,但每个测试类都会触发Spring Boot应用重启,似乎会为每个测试类重建ApplicationContext,导致整个构建流程耗时长达一小时。请问如何实现所有测试一次性运行,避免应用重复重启?
Spring Boot测试默认会尝试复用ApplicationContext,但出现上下文缓存不命中时会触发重建。以下是针对性的解决方法:
1. 统一测试上下文配置
确保所有测试类的上下文配置完全一致:
- 基类已包含
@SpringBootTest、@ActiveProfiles、@AutoConfigureMockMvc等核心注解,测试类继承后不要添加任何会改变上下文配置的额外注解(比如不同的@ActiveProfiles、自定义@TestConfiguration)。 - 如果
@SpringBootTest指定了classes或webEnvironment参数,所有测试类的该参数必须完全相同。
2. 移除冗余注解
Spring Boot 2.1及以上版本中,@SpringBootTest已默认集成@ExtendsWith(SpringExtension.class),测试类无需重复添加,冗余注解可能导致缓存判断异常。修改后的测试类代码:
public class ATestClass extends ApplicationTests { @Test // 测试方法 }
3. 对齐包结构
确保所有测试类与主应用类(带@SpringBootApplication的类)处于同一根包或其子包下。如果包结构不一致,需在基类的@SpringBootTest中显式指定主类:
@SpringBootTest(classes = YourMainApplication.class)
4. 配置Surefire复用JVM
默认情况下Surefire会为测试创建多个JVM进程,导致上下文缓存无法跨进程复用。修改插件配置,让所有测试在同一个JVM中运行:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <forkCount>1</forkCount> <reuseForks>true</reuseForks> <includes> <include>**/*Test*.java</include> </includes> </configuration> </plugin>
forkCount=1表示仅创建一个JVM进程,reuseForks=true表示复用该进程运行所有测试,保证上下文缓存不丢失。
5. 避免上下文污染
如果测试方法修改了单例Bean的属性或全局状态,Spring Boot会标记上下文为"已污染",不再复用。需确保测试执行后不改变全局状态;若无法避免,可使用@DirtiesContext标记污染上下文的测试,但尽量少用,因为它会强制重建上下文。
内容的提问来源于stack exchange,提问作者user204069

