1. 概述
本文将介绍如何直接通过 Java 代码运行 JUnit 测试。这种能力在某些场景下非常实用,比如:
✅ 动态触发测试流程
✅ 嵌入式测试执行(如 CLI 工具、插件系统)
✅ 自定义测试调度器或 CI 扩展
如果你刚接触 JUnit,或者正准备升级到 JUnit 5,可以参考我们其他关于 JUnit 的系列教程。
2. Maven 依赖
要支持 JUnit 4 和 JUnit 5 的程序化调用,需要引入以下核心依赖:
<dependencies>
<!-- JUnit 5 执行引擎 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<!-- JUnit 平台启动器(核心 API) -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.10.0</version>
</dependency>
<!-- JUnit 4 支持 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
📌 最新版依赖可在 Maven Central 查找:
⚠️ 注意:junit-platform-launcher
不要设为 test
范围,否则主程序无法访问。
3. 运行 JUnit 4 测试
3.1. 测试用例准备
我们先定义两个简单的测试类作为演示:
public class FirstUnitTest {
@Test
public void whenThis_thenThat() {
assertTrue(true);
}
@Test
public void whenSomething_thenSomething() {
assertTrue(true);
}
@Test
public void whenSomethingElse_thenSomethingElse() {
assertTrue(true);
}
}
public class SecondUnitTest {
@Test
public void whenSomething_thenSomething() {
assertTrue(true);
}
@Test
public void whensomethingElse_thenSomethingElse() {
assertTrue(true);
}
}
这些类使用 JUnit 4 的 @Test
注解标记测试方法。其他注解如 @Before
、@After
也常用,但不在本文讨论范围。
3.2. 运行单个测试类
通过 JUnitCore
类即可从 Java 代码启动测试,搭配 TextListener
可输出结果到控制台:
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(FirstUnitTest.class);
输出示例:
Running one test class:
..
Time: 0.019
OK (3 tests)
✅ 简单粗暴,适合快速验证。
3.3. 运行多个测试类
只需将多个类传入 run()
方法即可:
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
Result result = junit.run(
FirstUnitTest.class,
SecondUnitTest.class);
resultReport(result);
结果通过 Result
对象获取,辅助方法如下:
public static void resultReport(Result result) {
System.out.println("Finished. Result: Failures: " +
result.getFailureCount() + ". Ignored: " +
result.getIgnoreCount() + ". Tests run: " +
result.getRunCount() + ". Time: " +
result.getRunTime() + "ms.");
}
输出:
Finished. Result: Failures: 0. Ignored: 0. Tests run: 5. Time: 123ms.
3.4. 运行测试套件(Test Suite)
若想把多个测试类组合成一个逻辑单元,可使用 @RunWith(Suite.class)
定义测试套件:
@RunWith(Suite.class)
@Suite.SuiteClasses({
FirstUnitTest.class,
SecondUnitTest.class
})
public class MyTestSuite {
}
运行方式与普通类一致:
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
Result result = junit.run(MyTestSuite.class);
resultReport(result);
✅ 适合组织模块化测试集,结构清晰。
3.5. 重复执行测试
JUnit 4 提供了 RepeatedTest
,可用于压力测试或验证随机性逻辑:
Test test = new JUnit4TestAdapter(FirstUnitTest.class);
RepeatedTest repeatedTest = new RepeatedTest(test, 5);
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(repeatedTest);
📌 注意:需使用 JUnit4TestAdapter
包装测试类。
更进一步,还可以动态构建测试套件并设置不同重复次数:
TestSuite mySuite = new TestSuite();
mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(FirstUnitTest.class), 5));
mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(SecondUnitTest.class), 3));
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(mySuite);
⚠️ ActiveTestSuite
已过时,建议使用标准 TestSuite
。
4. 运行 JUnit 5 测试
4.1. 测试用例准备
沿用之前的测试类,但需改为 JUnit 5 的注解和断言:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class FirstUnitTest {
@Test
void whenThis_thenThat() {
assertTrue(true);
}
// 其他方法略
}
差异点:
@Test
来自org.junit.jupiter.api
- 断言方法在
Assertions
类中 - 方法可为
private
或void
,不限public
4.2. 运行单个测试类
JUnit 5 使用 Launcher 模型,流程如下:
- 构建
LauncherDiscoveryRequest
- 创建
Launcher
- 发现测试计划(
TestPlan
) - 注册监听器
- 执行
示例代码:
public class RunJUnit5TestsFromJava {
SummaryGeneratingListener listener = new SummaryGeneratingListener();
public void runOne() {
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectClass(FirstUnitTest.class))
.build();
Launcher launcher = LauncherFactory.create();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
}
}
📌 SummaryGeneratingListener
是 JUnit 提供的便捷监听器,用于收集执行摘要。
4.3. 运行多个测试类
通过包扫描 + 类名过滤,轻松批量运行测试:
public void runAll() {
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectPackage("com.example.junit5"))
.filters(includeClassNamePatterns(".*Test"))
.build();
Launcher launcher = LauncherFactory.create();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
}
关键点:
selectPackage()
:指定根包路径includeClassNamePatterns()
:正则匹配类名,如*Test
、*IT
✅ 这种方式非常适合自动化集成测试调度。
4.4. 获取测试输出
通过监听器获取执行结果:
public static void main(String[] args) {
RunJUnit5TestsFromJava runner = new RunJUnit5TestsFromJava();
runner.runAll();
TestExecutionSummary summary = runner.listener.getSummary();
summary.printTo(new PrintWriter(System.out));
}
输出示例:
Test run finished after 177 ms
[ 7 containers found ]
[ 0 containers skipped ]
[ 7 containers started ]
[ 0 containers aborted ]
[ 7 containers successful ]
[ 0 containers failed ]
[ 10 tests found ]
[ 0 tests skipped ]
[ 10 tests started ]
[ 0 tests aborted ]
[ 10 tests successful ]
[ 0 tests failed ]
📌 TestExecutionSummary
提供了丰富的统计信息,可用于生成报告或触发后续逻辑。
5. 总结
本文系统介绍了如何从 Java 应用中以编程方式运行 JUnit 4 和 JUnit 5 测试,涵盖:
✅ 单类 / 多类执行
✅ 测试套件组织
✅ 重复测试(JUnit 4)
✅ 基于 Launcher 的现代模型(JUnit 5)
这些技巧在构建自定义测试工具链时非常有用,比如:
- 内嵌测试面板(IDE 插件)
- CLI 测试运行器
- CI/CD 中的条件测试触发
所有示例代码均已上传至 GitHub:
踩坑提醒:
⚠️ JUnit 5 的 launcher
必须注册监听器才能拿到结果
⚠️ junit-platform-launcher
依赖不能放在 test
scope
⚠️ 包扫描时注意类路径是否正确加载
掌握这些 API,你就拥有了“控制测试执行”的能力,不再是被动等待构建工具驱动测试了。