@extendwith 是 junit 5 启用自定义扩展的核心注解,通过实现 extension 接口(如 beforeeachcallback、aftereachcallback)在测试生命周期各阶段执行逻辑,并支持 @registerextension 实例化带状态扩展。

在 JUnit 5 中,@ExtendWith 是启用自定义扩展的核心注解,它允许你将自定义的生命周期处理器(即实现 Extension 接口的类)注入到测试执行流程中,从而在测试前、后或异常时执行特定逻辑。
理解 Extension 的生命周期钩子
JUnit 5 的扩展机制基于接口回调,常见可重写的方法包括:
-
beforeEach(ExtensionContext):每个@Test方法执行前调用 -
afterEach(ExtensionContext):每个@Test方法执行后调用 -
beforeAll(ExtensionContext):整个测试类所有方法执行前调用(需静态方法或配合@RegisterExtension) -
afterAll(ExtensionContext):整个测试类所有方法执行后调用 -
handleTestExecutionException(TestExtensionContext, Throwable):测试抛出异常时拦截处理
编写一个简单的日志扩展
比如想在每次测试前后打印日志,可定义如下扩展:
public class LoggingExtension implements BeforeEachCallback, AfterEachCallback {
@Override
public void beforeEach(ExtensionContext context) {
System.out.println("▶ 开始测试: " + context.getDisplayName());
}
@Override
public void afterEach(ExtensionContext context) {
System.out.println("◀ 结束测试: " + context.getDisplayName());
}
}
然后在测试类上使用:
@ExtendWith(LoggingExtension.class)
class MyServiceTest {
@Test
void testSomething() {
// 测试逻辑
}
}
使用 @RegisterExtension 实现实例级扩展
若扩展需要持有状态(如共享资源、计数器),推荐用 @RegisterExtension 字段方式注册,而非 @ExtendWith 类级别声明:
class MyServiceTest {
@RegisterExtension
LoggingExtension logging = new LoggingExtension(); // 可带构造参数或初始化逻辑
@Test
void testWithState() {
// logging 可维护内部状态,如调用次数
}
}
这种方式支持依赖注入、构造参数传递,且生命周期与测试类实例绑定,更灵活可靠。
组合多个扩展或复用已有扩展
可以同时启用多个扩展,顺序按声明顺序执行:
@ExtendWith({LoggingExtension.class, DatabaseCleanupExtension.class})
class IntegrationTest { ... }
也可继承已有扩展(如 TempDirectoryExtension)或组合使用 Spring 扩展:@ExtendWith(SpringExtension.class),配合 @ContextConfiguration 启动测试上下文。
不复杂但容易忽略的是:扩展类必须有无参构造器(除非用 @RegisterExtension 手动构造),且不能是匿名类或局部类。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











