如何正确使用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
相关产品推荐
相关产品推荐

