You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java测试中Mock方法实现?JUnit+Mockito遇空指针异常求助

问题分析与解决方案

你遇到的空指针问题,核心原因是当前用了@Spy修饰ClassB,Mockito默认会执行methodB的真实逻辑,而真实的methodB会调用ClassC的methodC,但你没对ClassC做任何mock或实例化,所以触发空指针。

针对你的需求(只测试ClassA的methodA),不需要mockClassC,直接让methodB不执行自身实现即可,具体有两种方案:


方案1:把ClassB改成完全Mock对象

测试ClassA时,ClassB只是ClassA的依赖,我们只需要预设methodB的返回值,不需要它的真实逻辑。把ClassB的@Spy改成@Mock,就能彻底隔离它的真实调用链:

@ExtendWith(MockitoExtension.class)
public class ClassATest {

    @Mock
    APIGatewayProxyRequestEvent event;

    @Mock
    Context context;

    @Mock // 替换@Spy为@Mock,创建完全Mock的ClassB
    ClassB classB;

    @InjectMocks
    ClassA classA; // 不需要@Spy,用真实的ClassA对象,仅注入依赖mock

    @Test
    @DisplayName("everything should pass")
    public void testMethodA() throws Exception {
 
        Person p = new Person("xyz", "abc", 12345, true);
        // Mock的ClassB不会执行真实methodB,直接返回预设值
        when(classB.methodB(any(Molecule.class), eq("abc"), eq(12345), eq(null))).thenReturn(p);

        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("id", "12345");
        when(event.getHeaders()).thenReturn(headerMap);
        when(event.getBody()).thenReturn("{name:hello}");

        assertEquals(classA.methodA(event, context).getStatusCode(), 500);
    }
}

方案2:若必须用@Spy,改用doReturn跳过真实方法执行

如果因为某些原因需要保留ClassB为@Spy(比如需要mock它的部分方法,保留其他方法的真实逻辑),则要用doReturn替代when语法——when会先执行一次真实方法再设置返回值,而doReturn直接跳过真实调用:

// 替换原测试方法中的when语句
doReturn(p).when(classB).methodB(any(Molecule.class), eq("abc"), eq(12345), eq(null));

这样methodB的真实逻辑不会被触发,自然也就不会调用ClassC的methodC,空指针问题就能解决。


总结

测试ClassA的methodA时,核心是隔离ClassA的外部依赖:

  • ClassB作为依赖,只需要提供预设的返回值即可,不需要执行真实逻辑
  • 不需要额外mockClassC,因为我们已经切断了ClassB到ClassC的调用链

内容的提问来源于stack exchange,提问作者Tanu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 06:20:27