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

如何正确使用Mockito.spy验证InputStream的close方法调用?

解决Mockito Spy监控InputStream时的NullPointerException问题

出现这个NPE的原因是:ByteArrayInputStream的readAllBytes()是Java 9引入的默认方法,Mockito 4.x版本对默认方法的Spy代理存在缺陷,导致调用该方法时无法正确访问原对象的内部original字段,从而抛出空指针异常。

以下是几种可行的解决方式:

方式一:使用Mock替代Spy(推荐)

既然测试目标只是验证close()方法是否被调用,不需要实际执行readAllBytes()的读取逻辑,直接用Mock对象更简单,还能避免原类内部逻辑的干扰:

@Test
public void testConsumeAndClose() throws IOException {
    // 创建InputStream的Mock对象
    InputStream inputStream = mock(InputStream.class);
    // Stub readAllBytes方法,避免调用时抛出异常
    when(inputStream.readAllBytes()).thenReturn("Hello World".getBytes());

    consumeAndClose(inputStream);
    // 验证close方法是否被调用
    verify(inputStream).close();
    // 可选:验证readAllBytes也被调用
    verify(inputStream).readAllBytes();
}

方式二:用BufferedInputStream包装后再Spy

如果确实需要执行真实的读取逻辑,可以用BufferedInputStream包装ByteArrayInputStream后再Spy——因为BufferedInputStream重写了readAllBytes()方法(不是默认方法),Mockito能正确代理它的方法调用:

@Test
public void testSpyWithBufferedStream() throws IOException {
    InputStream inputStream = spy(new BufferedInputStream(
            new ByteArrayInputStream("Hello World".getBytes())
    ));
    consumeAndClose(inputStream);
    verify(inputStream).close();
}

方式三:自定义InputStream子类

也可以自己实现一个继承自ByteArrayInputStream的子类,再对这个子类进行Spy,绕过默认方法的代理问题:

class TestByteArrayInputStream extends ByteArrayInputStream {
    public TestByteArrayInputStream(byte[] buf) {
        super(buf);
    }
}

@Test
public void testSpyCustomStream() throws IOException {
    InputStream inputStream = spy(new TestByteArrayInputStream("Hello World".getBytes()));
    consumeAndClose(inputStream);
    verify(inputStream).close();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:20:29