Mock注解方法遇NPE:如何触发table.annotationType().getMethod("name")抛NoSuchMethodException
解决Mockito模拟注解时抛出NoSuchMethodException的问题
我来帮你搞定这个Mockito模拟过程中的异常抛出问题!你遇到的核心需求是让table.annotationType().getMethod("name")触发NoSuchMethodException,但目前可能因为深度mock的使用方式不对,或者stub写法有误导致空指针(NPE)或异常未正确抛出。
问题分析
首先要明确:Table应该是一个注解类型(即@interface Table),因为annotationType()是java.lang.annotation.Annotation接口的方法,只有注解类才会实现这个方法并返回自身的Class对象。你使用了RETURNS_DEEP_STUBS,Mockito会自动为嵌套调用生成mock对象,但如果没正确stub嵌套方法的行为,就可能出现NPE或达不到预期效果。
解决方案1:使用深度mock(RETURNS_DEEP_STUBS)正确Stub
如果你想继续用深度mock,需要确保链式stub的写法正确,并且为异常提供实例或类:
import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.mockito.Mockito.when; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; public class SupportTableTest { @Mock(answer = RETURNS_DEEP_STUBS) private Table table; @Test(expected = NoSuchMethodException.class) public void testGetSupportClassesDatabaseThrowException() throws NoSuchMethodException { // 初始化mock对象(推荐用openMocks替代旧的initMocks) MockitoAnnotations.openMocks(this); // 正确Stub嵌套调用,指定抛出异常 when(table.annotationType().getMethod("name")) .thenThrow(new NoSuchMethodException("Method 'name' does not exist on Table annotation")); // 执行调用,触发异常 table.annotationType().getMethod("name"); } }
关键注意点:
- 用
MockitoAnnotations.openMocks(this)替代旧的initMocks,这是Mockito 3.4+推荐的初始化方式。 thenThrow可以传入异常实例或者异常类(比如thenThrow(NoSuchMethodException.class)),两种写法都有效,但传入实例可以自定义异常信息,方便调试。- 确保
Table是合法的注解类型,否则annotationType()的返回值会不符合预期,导致后续调用出错。
解决方案2:手动分层Mock(更可控)
深度mock虽然方便,但有时候会让调试变复杂。你可以手动mock每个层级的对象,让逻辑更清晰:
import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.mockito.Mockito.when; public class SupportTableTest { @Mock private Table table; @Mock private Class<Table> tableAnnotationClass; @Test(expected = NoSuchMethodException.class) public void testGetSupportClassesDatabaseThrowException() throws NoSuchMethodException { MockitoAnnotations.openMocks(this); // 第一步:让table的annotationType返回我们mock的Class对象 when(table.annotationType()).thenReturn(tableAnnotationClass); // 第二步:让这个mock的Class对象的getMethod抛出异常 when(tableAnnotationClass.getMethod("name")).thenThrow(NoSuchMethodException.class); // 执行调用 table.annotationType().getMethod("name"); } }
这种写法的好处是每个mock对象的行为都清晰可控,遇到问题时更容易定位哪个环节出了问题,适合复杂的mock场景。
常见坑点排查
- 空指针异常(NPE):如果之前出现NPE,大概率是因为
table.annotationType()返回了null,而不是mock的Class对象。这时候要检查是否正确初始化了mock对象,或者是否因为Table不是注解类型导致annotationType()返回值异常。 - 异常未抛出:如果执行后没触发
NoSuchMethodException,要检查stub的方法签名是否完全匹配(比如getMethod的参数是否正确,这里是"name",没有重载参数),以及stub的顺序是否在调用之前。
内容的提问来源于stack exchange,提问作者Oleksandr Stefanovskyi
相关产品推荐
相关产品推荐

