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

如何在JUnit Mockito中验证并捕获InputStream的内容?

解决方案

你遇到的问题核心是:try-with-resources会在commandRunner.run()执行完成后立刻关闭输入流,导致Mockito捕获到的流对象在验证阶段已经处于关闭状态,无法读取内容。解决的关键是在流仍处于打开状态时(即run方法执行过程中)读取并保存流的内容,而非等到流关闭后再操作流对象。

下面是两种可行的实现方式:

方式一:使用Mockito Answer暂存流内容

通过doAnswer定义mock对象的行为,在commandRunner.run()被调用的瞬间读取输入流内容并暂存,后续再验证内容是否符合预期:

@Test
public void testHappyPath() throws IOException {
    ClassLoader classLoader = this.getClass().getClassLoader();
    File file = new File(classLoader.getResource("MyTestInputFile.txt").getFile());
    
    // 预先读取预期的文件内容
    byte[] expectedContent = Files.readAllBytes(file.toPath());
    AtomicReference<byte[]> actualContent = new AtomicReference<>();

    // 定义mock的run方法行为:读取输入流内容并暂存
    doAnswer(invocation -> {
        InputStream inputStream = invocation.getArgument(1);
        actualContent.set(inputStream.readAllBytes());
        return null;
    }).when(commandRunner).run(anyString(), any(InputStream.class));

    // 执行被测方法
    commandRunnerInputFile.run("MyApplication.exe", file);

    // 验证方法调用及内容匹配
    verify(commandRunner).run(eq("MyApplication.exe"), any(InputStream.class));
    assertArrayEquals(expectedContent, actualContent.get());
    // 验证第一个字符为'c'
    assertEquals('c', (char) actualContent.get()[0]);
}

方式二:直接在Answer中完成内容验证

如果不需要暂存内容,也可以在Answer内部直接完成断言,省去后续的变量验证步骤:

@Test
public void testHappyPath() throws IOException {
    ClassLoader classLoader = this.getClass().getClassLoader();
    File file = new File(classLoader.getResource("MyTestInputFile.txt").getFile());
    String expectedContent = Files.readString(file.toPath());

    // 调用run方法时直接读取流内容并断言
    doAnswer(invocation -> {
        InputStream is = invocation.getArgument(1);
        String actualContent = new String(is.readAllBytes());
        assertEquals(expectedContent, actualContent);
        return null;
    }).when(commandRunner).run(eq("MyApplication.exe"), any(InputStream.class));

    commandRunnerInputFile.run("MyApplication.exe", file);
    
    // 确保方法确实被调用
    verify(commandRunner).run(eq("MyApplication.exe"), any(InputStream.class));
}

注意事项

  • Java 9及以上支持InputStream.readAllBytes()方法,若使用Java 8,可借助IOUtils.toByteArray(is)(Apache Commons IO工具类)或手动实现流读取逻辑。
  • 禁止捕获InputStream对象后在验证阶段读取内容,此时流已被try-with-resources自动关闭,必然抛出流关闭异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:50:21