JUnit 5 中获取测试类、测试方法及属性的注解


JUnit 5 中获取测试类、测试方法及属性的注解

JUnit 5 提供了强大的扩展机制,允许通过 ExtensionContext 获取测试类、测试方法及其属性上的注解信息。以下是具体实现方法和示例:


一、核心 API
  1. ExtensionContext

    • 提供测试执行的上下文信息,包括测试类、方法、注解等。
    • 通过扩展接口(如 BeforeEachCallbackParameterResolver)访问。
  2. AnnotatedElement

    • 表示可注解的元素(如类、方法、字段)。
    • 提供 getAnnotation()getAnnotations() 方法获取注解。

二、获取注解的步骤
  1. 实现扩展接口
    选择适合的扩展接口(如 BeforeEachCallbackTestExecutionCondition)。
  2. 通过 ExtensionContext 获取元素
    使用 getRequiredTestClass()getRequiredTestMethod() 等方法。
  3. 获取注解信息
    调用 getAnnotation()getAnnotations() 方法。

三、具体示例
示例 1:获取测试类上的注解
java 复制代码
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:获取测试方法上的注解
java 复制代码
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:获取测试类属性上的注解
java 复制代码
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:获取所有注解
java 复制代码
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,可以轻松获取测试类、方法和属性上的注解信息,适用于以下场景:

  • 动态配置测试:根据注解值调整测试行为。
  • 生成测试报告:提取注解信息生成详细报告。
  • 扩展功能:实现自定义注解处理器(如依赖注入、条件测试)。

建议结合具体需求选择合适的扩展接口,并注意注解的继承和组合特性。

相关推荐
少许极端10 分钟前
算法奇妙屋(七)-字符串操作
java·开发语言·数据结构·算法·字符串操作
懒羊羊不懒@13 分钟前
Java基础语法—字面量、变量详解、存储数据原理
java·开发语言
望获linux16 分钟前
【实时Linux实战系列】实时 Linux 的自动化基准测试框架
java·大数据·linux·运维·网络·elasticsearch·搜索引擎
Code blocks27 分钟前
GB28181视频服务wvp部署(一)
java·spring boot·后端
我命由我1234533 分钟前
Spring Boot - Spring Boot 静态资源延迟响应(使用拦截器、使用过滤器、使用 ResourceResolver)
java·spring boot·后端·spring·java-ee·intellij-idea·intellij idea
Xzh042339 分钟前
前后端学习的交界
java·ajax·maven·axios·测试
豆沙沙包?1 小时前
2025年--Lc201- 378. 有序矩阵中第 K 小的元素(排序)--Java版
java·线性代数·矩阵
华仔啊1 小时前
3 分钟让你彻底搞懂 Spring 观察者和发布者模式的本质区别
java·后端
没有bug.的程序员1 小时前
服务治理与 API 网关:微服务流量管理的艺术
java·分布式·微服务·架构·wpf
宠友信息1 小时前
java微服务驱动的社区平台:友猫社区的功能模块与实现逻辑
java·开发语言·微服务