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

如何Mock DataInputStream.read方法测试分段读大对象的循环逻辑?

问题根因

你的实现存在3个核心错误:

  1. doReturn中的stream.read(xxx)会在测试代码执行阶段立即执行,而非mock被业务代码调用时才触发,且DataInputStream不存在read(int)签名的方法,入参类型不匹配会直接触发异常。
  2. mock的read(byte[] buffer)方法默认不会自动将测试数据写入传入的buffer参数,就算返回了正确的读取字节数,业务代码拿到的buffer也是空值,会出现逻辑错误。
  3. 你已经直接将mockStream作为参数传入myMethod,whenNew的配置属于冗余代码,没有实际作用。
可行解决方案

方案1:通过Mockito Answer自定义read行为

如果你希望使用mock框架实现,可以通过Answer接口自定义read方法的逻辑,同时处理返回值和buffer写入:

@RunWith(MockitoJUnitRunner.class)
public class MyTestClass {
    @Test
    public void myTestMethod() throws IOException {
        int objectLength = 1024;
        byte[] testData = BytesDecoderSpec.generateRandomString(objectLength).getBytes(StandardCharsets.UTF_8);
        DataInputStream mockStream = Mockito.mock(DataInputStream.class);

        int firstReadLen = testData.length / 2;
        Mockito.when(mockStream.read(Mockito.any(byte[].class)))
                // 第一次调用返回一半长度
                .thenAnswer(invocation -> {
                    byte[] buffer = invocation.getArgument(0);
                    System.arraycopy(testData, 0, buffer, 0, firstReadLen);
                    return firstReadLen;
                })
                // 第二次调用返回剩余长度
                .thenAnswer(invocation -> {
                    byte[] buffer = invocation.getArgument(0);
                    int remainLen = testData.length - firstReadLen;
                    System.arraycopy(testData, firstReadLen, buffer, 0, remainLen);
                    return remainLen;
                })
                // 后续调用返回-1标记流结束
                .thenReturn(-1);

        MyRealClass realObject = new MyRealClass();
        ResultObject result = realObject.myMethod(mockStream, objectLength);
        // 补充断言逻辑验证结果正确性
    }
}

方案2:自定义分段输入流(更推荐,无mock框架依赖)

直接实现一个自定义InputStream,控制每次read的最大返回长度,完全规避mock框架的各类问题:

// 自定义分段输入流,限制单次读取的最大字节数
public class FragmentedByteArrayInputStream extends ByteArrayInputStream {
    private final int maxReadPerTime;

    public FragmentedByteArrayInputStream(byte[] buf, int maxReadPerTime) {
        super(buf);
        this.maxReadPerTime = maxReadPerTime;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int actualReadLen = Math.min(len, maxReadPerTime);
        return super.read(b, off, actualReadLen);
    }
}

测试代码直接使用该流即可:

@Test
public void myTestMethod() throws IOException {
    int objectLength = 1024;
    byte[] testData = BytesDecoderSpec.generateRandomString(objectLength).getBytes(StandardCharsets.UTF_8);
    // 配置单次最多读取512字节,模拟大文件分段读取场景
    FragmentedByteArrayInputStream bis = new FragmentedByteArrayInputStream(testData, 512);
    DataInputStream stream = new DataInputStream(bis);

    MyRealClass realObject = new MyRealClass();
    ResultObject result = realObject.myMethod(stream, objectLength);
    // 补充断言逻辑验证结果正确性
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:36:05