无测试框架时Java POJO测试执行原理:Surefire用何种运行器?
问题背景
我正在开发一个Java 11应用,编写了如下测试类:
public class HelloWorldTest { public void testGetHello() { assert("Hello World!".equals(HelloWorld.getHello())); } }
项目的pom.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>guru.springframework</groupId> <artifactId>helloworld</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>11</java.version> <maven.compiler.source>${java.version}</maven.compiler.source> <maven.compiler.target>${java.version}</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> </dependencies> </project>
执行mvn test时,HelloWorldTest被自动识别并执行。我知道Maven会引入Surefire插件,但想知道该插件用什么测试运行器识别并执行这个测试类,底层具体运作机制是什么?
解答
一、Surefire默认使用的测试运行器
你的测试类没有显式依赖JUnit、TestNG等测试框架,但Maven Surefire插件默认会自动引入JUnit 4的依赖(作为插件的传递依赖),并使用JUnit4Provider作为核心测试运行器。
这个运行器会通过以下规则识别测试类和方法:
- 类名以
Test结尾(或开头) - 方法名以
test开头、无参数、返回值为void
这就是你的HelloWorldTest和testGetHello方法被识别的原因。
二、底层运作流程
Surefire插件执行测试的完整逻辑如下:
- 扫描测试类:在
test阶段,插件会自动扫描src/test/java目录下的所有类,按照上述命名规则筛选出候选测试类。 - 构建测试类路径:插件会整理测试所需的类路径,包括项目编译后的类、依赖jar包,以及插件自带的JUnit 4相关jar包。
- Fork独立JVM进程:默认情况下,Surefire会启动一个独立的JVM来执行测试(避免与Maven自身JVM环境冲突),并在启动参数中添加
-ea(启用Java断言)——这也是你的assert语句能生效的关键。 - 执行测试:
- 测试运行器
JUnit4Provider在新JVM中实例化你的HelloWorldTest类 - 通过反射找出所有符合命名规则的测试方法(即
testGetHello) - 依次调用这些方法,执行
assert语句;如果断言失败,会抛出AssertionError,运行器会捕获这个错误并标记测试失败
- 测试运行器
- 生成测试报告:运行器收集所有测试的结果(成功/失败/跳过),返回给Surefire插件,最终在
target/surefire-reports目录生成测试报告文件。
内容的提问来源于stack exchange,提问作者user2693135
相关产品推荐
相关产品推荐

