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

JUnit测试中如何比较两个ByteArrayInputStream?含报错问题

如何在JUnit中正确比较两个ByteArrayInputStream?

首先得说,你当前的报错完全是因为用错了比较方式——直接调用ByteArrayInputStream.toString()来比较,这个方法默认返回的是对象的内存标识(类名@哈希码),你看到的43195e57和333291e3就是两个不同对象的哈希值,所以JUnit肯定会判定不相等。而且你的代码里还有几个隐藏的坑,我一步步给你理清楚:

先揪出代码里的致命错误

你这行代码完全搞错了文件读取的逻辑:

ByteArrayInputStream uploadByteArrayInputStream = new ByteArrayInputStream(file.toString().getBytes());

FileInputStream.toString()根本不是读取文件内容,它返回的是java.io.FileInputStream@xxxx这种对象标识字符串,你把这个字符串转成字节数组上传,相当于上传了一堆毫无意义的字节,而不是你要的图片文件!这是核心问题之一。

正确比较ByteArrayInputStream的方法

要比较两个流的内容,本质是比较它们包含的字节数组,有两种常用的靠谱方式:

方式1:转成字节数组后用assertArrayEquals比较

因为ByteArrayInputStream内部持有字节缓冲区,支持reset()方法重置指针,所以我们可以先把流的内容转成字节数组,再比较:

// 重置上传流的指针(因为putObject已经把流读到末尾了)
uploadByteArrayInputStream.reset();
byte[] uploadBytes = IOUtils.toByteArray(uploadByteArrayInputStream);

// 把从MinIO获取的流转成字节数组
byte[] downloadedBytes = IOUtils.toByteArray(stream);

// 直接比较两个字节数组
assertArrayEquals(uploadBytes, downloadedBytes);

方式2:用Apache Commons IO的IOUtils.contentEquals直接比较流

如果你不想手动转数组,可以用IOUtils提供的工具方法,它会自动读取两个流的内容并逐字节比较:

// 重置上传流指针
uploadByteArrayInputStream.reset();
// 直接断言两个流内容相同
assertTrue(IOUtils.contentEquals(uploadByteArrayInputStream, stream));

⚠️ 注意:这个方法会把两个流都读到末尾,如果之后还要用流的话,需要重新获取或者提前保存内容。

给你修正后的完整测试代码

我把所有问题都修复了,包括文件读取、流的复用、资源自动关闭(用try-with-resources避免内存泄漏):

@Test 
public void fileIsSame() throws IOException, InvalidEndpointException, InvalidPortException, InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, InvalidArgumentException, XmlPullParserException {
    // try-with-resources自动关闭文件流,不用手动close
    try (FileInputStream file = new FileInputStream("/Users/gauris/Documents/samplephoto/pexels-photo-46710.jpeg")) {
        String fileName = "pexels-photo-46710.jpeg";
        // 正确读取文件内容到字节数组
        byte[] fileBytes = IOUtils.toByteArray(file);
        // 基于字节数组创建ByteArrayInputStream(可以多次reset复用)
        ByteArrayInputStream uploadByteArrayInputStream = new ByteArrayInputStream(fileBytes);
        
        // 上传到MinIO,这里直接用字节数组的长度,比available()更可靠
        minioClient.putObject(bucketName, fileName, uploadByteArrayInputStream, fileBytes.length, "application/octet-stream");
        
        // 重置上传流的指针,准备后续比较
        uploadByteArrayInputStream.reset();
        
        // 用try-with-resources自动关闭MinIO返回的流
        try (InputStream stream = minioClient.getObject(bucketName, fileName)) {
            // 方法1:比较字节数组
            byte[] downloadedBytes = IOUtils.toByteArray(stream);
            assertArrayEquals("上传和下载的文件内容不一致", fileBytes, downloadedBytes);
            
            // 如果你想用方法2,需要重新获取流(因为上面已经把stream读完了)
            // try (InputStream newStream = minioClient.getObject(bucketName, fileName)) {
            //     assertTrue("上传和下载的文件内容不一致", IOUtils.contentEquals(uploadByteArrayInputStream, newStream));
            // }
        }
    }
}

最后再强调下关键要点

  • 永远不要用toString()比较流对象,这是在比较对象引用,不是内容;
  • 读取文件时,一定要用IOUtils.toByteArray()或者手动读取字节数组,不要调用流的toString();
  • 流一旦被读取到末尾,后续再读就拿不到内容了,要么提前保存字节数组,要么用reset()(仅限支持重置的流,比如ByteArrayInputStream);
  • 用try-with-resources管理流资源,避免手动关闭遗漏导致的资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:13:07