JUnit 5 中获取测试类、测试方法及属性的注解
JUnit 5 提供了强大的扩展机制,允许通过 ExtensionContext
获取测试类、测试方法及其属性上的注解信息。以下是具体实现方法和示例:
一、核心 API
-
ExtensionContext
- 提供测试执行的上下文信息,包括测试类、方法、注解等。
- 通过扩展接口(如
BeforeEachCallback
、ParameterResolver
)访问。
-
AnnotatedElement
- 表示可注解的元素(如类、方法、字段)。
- 提供
getAnnotation()
和getAnnotations()
方法获取注解。
二、获取注解的步骤
- 实现扩展接口
选择适合的扩展接口(如BeforeEachCallback
、TestExecutionCondition
)。 - 通过
ExtensionContext
获取元素
使用getRequiredTestClass()
、getRequiredTestMethod()
等方法。 - 获取注解信息
调用getAnnotation()
或getAnnotations()
方法。
三、具体示例
示例 1:获取测试类上的注解
java">import org.junit.jupiter.api.extension.*;public class ClassAnnotationExtension implements BeforeEachCallback {@Overridepublic 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 {@Testvoid testMethod() {Assertions.assertTrue(true);}
}
输出:
测试类显示名称: 用户服务测试
测试类标签: service
示例 2:获取测试方法上的注解
java">import org.junit.jupiter.api.extension.*;public class MethodAnnotationExtension implements BeforeEachCallback {@Overridepublic 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:获取测试类属性上的注解
java">import org.junit.jupiter.api.extension.*;public class FieldAnnotationExtension implements BeforeEachCallback {@Overridepublic 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 {@Mockprivate UserRepository userRepository;@Testvoid testMethod() {Assertions.assertTrue(true);}
}
输出:
找到 Mock 字段: userRepository
示例 4:获取所有注解
java">import org.junit.jupiter.api.extension.*;public class AllAnnotationsExtension implements BeforeEachCallback {@Overridepublic 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,可以轻松获取测试类、方法和属性上的注解信息,适用于以下场景:
- 动态配置测试:根据注解值调整测试行为。
- 生成测试报告:提取注解信息生成详细报告。
- 扩展功能:实现自定义注解处理器(如依赖注入、条件测试)。
建议结合具体需求选择合适的扩展接口,并注意注解的继承和组合特性。