应 mock class 等具体实现类而非 annotatedelement 接口,因其 getannotation 是可 stub 的普通方法;mock 接口本身因 default 方法限制不可靠。

在 Mockito 中直接模拟 AnnotatedElement.getAnnotation(Class<t>)</t> 方法的返回值,不能用常规的 when(...).thenReturn(...),因为 AnnotatedElement 是一个接口,而 getAnnotation 是它的默认方法(JDK 8+),Mockito 无法对默认方法打桩(除非使用 mockito-inline 并启用默认方法支持)。更常见、更可靠的做法是:**不 mock AnnotatedElement 接口本身,而是 mock 一个具体的实现类(如 Class、Method、Field 等),再对其 getAnnotation 方法进行 stubbing**。
✅ 推荐方式:Mock 具体的 AnnotatedElement 实现(如 Class)
Java 中 Class、Method、Field、Constructor 都实现了 AnnotatedElement。它们的 getAnnotation 是可重写/可 stub 的普通方法(非 default),Mockito 可以正常处理。
例如,mock 一个 Class 对象并指定其返回某个注解:
// 假设有自定义注解 @MyAnnotation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "";
}
<p>// 测试中
Class> mockClass = mock(Class.class);
MyAnnotation mockAnn = mock(MyAnnotation.class);
when(mockClass.getAnnotation(MyAnnotation.class)).thenReturn(mockAnn);</p><p>// 使用示例(比如被测代码调用了 clazz.getAnnotation(MyAnnotation.class))
assertThat(mockClass.getAnnotation(MyAnnotation.class)).isSameAs(mockAnn);
</p>⚠️ 注意事项:避免 mock AnnotatedElement 接口本身
以下写法无效或不可靠:
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
AnnotatedElement mockAE = mock(AnnotatedElement.class); // ❌ 不推荐 when(mockAE.getAnnotation(MyAnnotation.class)).thenReturn(mockAnn); // ⚠️ 可能抛 UnsupportedOperationException 或返回 null
原因:
- AnnotatedElement 是接口,且 getAnnotation 在 JDK 中是 default 方法(自 Java 8 起);
- 经典 Mockito(无 inline)无法 stub 接口的 default 方法;
- 即使启用 mockito-inline,也需额外配置(mock-maker-inline),且行为不如 mock 具体类型稳定。
? 替代方案:使用真实对象 + 自定义注解(更自然)
如果只是为了测试注解存在性或值,最简洁的方式是用真实类 + 运行时注解,无需 mock:
- 定义一个带
@MyAnnotation的测试类(或用@RunWith(MockitoJUnitRunner.class)配合@Mock注入) - 通过
SomeClass.class.getAnnotation(MyAnnotation.class)获取真实注解实例 - 若需控制注解属性值,可用 TypeTools 或反射构造动态代理,但通常没必要
? 小技巧:快速创建注解代理(按需)
如果必须“伪造”一个注解实例(比如注解类不可实例化),可用 java.lang.reflect.Proxy:
MyAnnotation fakeAnn = (MyAnnotation) Proxy.newProxyInstance(
getClass().getClassLoader(),
new Class[]{MyAnnotation.class},
(proxy, method, args) -> {
if ("value".equals(method.getName())) return "test-value";
if ("annotationType".equals(method.getName())) return MyAnnotation.class;
return null;
}
);
when(mockClass.getAnnotation(MyAnnotation.class)).thenReturn(fakeAnn);
不过多数场景下,直接 mock(MyAnnotation.class) + when(...).thenReturn(...) 已足够。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










