JUnit 5 中获取测试类、测试方法及属性的注解
JUnit 5 中获取测试类、测试方法及属性的注解
JUnit 5 提供了强大的扩展机制,允许通过 ExtensionContext
获取测试类、测试方法及其属性上的注解信息。以下是具体实现方法和示例:
一、核心 API
-
ExtensionContext
- 提供测试执行的上下文信息,包括测试类、方法、注解等。
- 通过扩展接口(如
BeforeEachCallback
、ParameterResolver
)访问。
-
AnnotatedElement
- 表示可注解的元素(如类、方法、字段)。
- 提供
getAnnotation()
和getAnnotations()
方法获取注解。
二、获取注解的步骤
- 实现扩展接口
选择适合的扩展接口(如BeforeEachCallback
、TestExecutionCondition
)。 - 通过
ExtensionContext
获取元素
使用getRequiredTestClass()
、getRequiredTestMethod()
等方法。 - 获取注解信息
调用getAnnotation()
或getAnnotations()
方法。
三、具体示例
示例 1:获取测试类上的注解
import org.junit.jupiter.api.extension.*;
public class ClassAnnotationExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) {
// 获取测试类
Class<?> testClass = context.getRequiredTestClass();
// 获取类上的注解
DisplayName displayName = testClass.getAnnotation(DisplayName.class);
if (displayName != null) {
System.out.println("测试类显示名称: " + displayName.value());
}
Tag tag = testClass.getAnnotation(Tag.class);
if (tag != null) {
System.out.println("测试类标签: " + tag.value());
}
}
}
// 使用扩展
@DisplayName("用户服务测试")
@Tag("service")
@ExtendWith(ClassAnnotationExtension.class)
class UserServiceTest {
@Test
void testMethod() {
Assertions.assertTrue(true);
}
}
输出:
测试类显示名称: 用户服务测试
测试类标签: service
示例 2:获取测试方法上的注解
import org.junit.jupiter.api.extension.*;
public class MethodAnnotationExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) {
// 获取测试方法
Method testMethod = context.getRequiredTestMethod();
// 获取方法上的注解
DisplayName displayName = testMethod.getAnnotation(DisplayName.class);
if (displayName != null) {
System.out.println("测试方法显示名称: " + displayName.value());
}
Tag tag = testMethod.getAnnotation(Tag.class);
if (tag != null) {
System.out.println("测试方法标签: " + tag.value());
}
}
}
// 使用扩展
@ExtendWith(MethodAnnotationExtension.class)
class UserServiceTest {
@Test
@DisplayName("测试用户保存")
@Tag("save")
void testSaveUser() {
Assertions.assertTrue(true);
}
}
输出:
测试方法显示名称: 测试用户保存
测试方法标签: save
示例 3:获取测试类属性上的注解
import org.junit.jupiter.api.extension.*;
public class FieldAnnotationExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) {
// 获取测试类
Class<?> testClass = context.getRequiredTestClass();
// 遍历所有字段
for (Field field : testClass.getDeclaredFields()) {
// 获取字段上的注解
Mock mock = field.getAnnotation(Mock.class);
if (mock != null) {
System.out.println("找到 Mock 字段: " + field.getName());
}
}
}
}
// 使用扩展
@ExtendWith(FieldAnnotationExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Test
void testMethod() {
Assertions.assertTrue(true);
}
}
输出:
找到 Mock 字段: userRepository
示例 4:获取所有注解
import org.junit.jupiter.api.extension.*;
public class AllAnnotationsExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) {
// 获取测试类
Class<?> testClass = context.getRequiredTestClass();
// 获取类上的所有注解
Annotation[] classAnnotations = testClass.getAnnotations();
System.out.println("测试类注解: " + Arrays.toString(classAnnotations));
// 获取测试方法
Method testMethod = context.getRequiredTestMethod();
// 获取方法上的所有注解
Annotation[] methodAnnotations = testMethod.getAnnotations();
System.out.println("测试方法注解: " + Arrays.toString(methodAnnotations));
}
}
// 使用扩展
@DisplayName("用户服务测试")
@Tag("service")
@ExtendWith(AllAnnotationsExtension.class)
class UserServiceTest {
@Test
@DisplayName("测试用户保存")
@Tag("save")
void testSaveUser() {
Assertions.assertTrue(true);
}
}
输出:
测试类注解: [@org.junit.jupiter.api.DisplayName(value=用户服务测试), @org.junit.jupiter.api.Tag(value=service)]
测试方法注解: [@org.junit.jupiter.api.DisplayName(value=测试用户保存), @org.junit.jupiter.api.Tag(value=save)]
四、总结
通过 ExtensionContext
和反射 API,可以轻松获取测试类、方法和属性上的注解信息,适用于以下场景:
- 动态配置测试:根据注解值调整测试行为。
- 生成测试报告:提取注解信息生成详细报告。
- 扩展功能:实现自定义注解处理器(如依赖注入、条件测试)。
建议结合具体需求选择合适的扩展接口,并注意注解的继承和组合特性。