Maven中Spring Boot测试非静态@BeforeAll方法报错排查
Gradle项目中已实现带有非静态@BeforeAll方法的Spring Boot测试,迁移至Maven项目后测试无法执行,报错InvalidTestClassError: Invalid test class。若改用JUnit4的@Test注解,会出现@BeforeAll方法不执行或提示BeforeAll must be static的问题。测试逻辑与Gradle项目完全一致,仅构建工具不同。
Gradle配置(build.gradle)
dependencies { testImplementation "org.springframework.boot:spring-boot-starter-test:${spring_boot_version}" implementation 'junit:junit:4.13.1' .... } tasks.named('test') { useJUnitPlatform() }
测试类代码
抽象基类
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = {DeardiaryApplication.class}) @WebAppConfiguration public abstract class AbstractTest { protected MockMvc mvc; private ObjectMapper objectMapper = new ObjectMapper(); @Autowired WebApplicationContext webApplicationContext; protected void setUp() { mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } ... }
测试子类
import org.junit.jupiter.api.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class DatabaseTest extends AbstractTest { @Autowired private ExerciseInterface exerciseService; @BeforeAll public void init() { setUp(); exerciseDto = exerciseService.getByExerciseType(ExerciseTypeEnum.SNATCH).get(0); } @Test .... }
Maven配置(pom.xml)
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring.boot.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring.boot.version}</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M8</version> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency> </dependencies> </plugin> </plugins> </build>
解决方案
核心问题
测试类混合了JUnit4(@RunWith)和JUnit5(@TestInstance、@BeforeAll)注解,导致Maven Surefire插件无法正确识别执行引擎。Gradle的useJUnitPlatform()可兼容混合场景,但Maven需明确配置并避免注解冲突。
步骤1:统一依赖,移除冗余配置
Spring Boot Starter Test已包含JUnit5核心依赖,无需单独引入junit-jupiter-api、junit-jupiter-engine,同时排除JUnit4依赖避免冲突:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring.boot.version}</version> <scope>test</scope> <exclusions> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
步骤2:替换JUnit4注解为JUnit5规范
将抽象基类的@RunWith(SpringJUnit4ClassRunner.class)替换为JUnit5的Spring扩展注解@ExtendWith(SpringExtension.class):
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.web.WebAppConfiguration; import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(SpringExtension.class) @SpringBootTest(classes = {DeardiaryApplication.class}) @WebAppConfiguration public abstract class AbstractTest { // 原有代码不变 }
测试子类保留JUnit5的@TestInstance(TestInstance.Lifecycle.PER_CLASS)和@BeforeAll,确保@Test使用org.junit.jupiter.api.Test注解。
步骤3:简化Surefire插件配置
使用稳定版Surefire插件,无需额外指定JUnit5引擎依赖:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring.boot.version}</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.1.2</version> </plugin> </plugins> </build>
验证
执行mvn test命令,测试类应正常执行,非静态@BeforeAll方法会在类初始化时执行一次。
内容的提问来源于stack exchange,提问作者hhrzc

