如何验证Spring Resource返回的图片下载结果?单元测试异常排查
问题原因及解决方案
核心问题
测试失败的根本原因是InputStream的一次性读取特性:你在测试中先将同一个InputStream对象读取到imgAsBytes数组,此时流的指针已经移动到末尾;之后又把这个已经耗尽的流返回给Mock服务,导致控制器处理时无法读取到任何内容,最终返回空的响应体。
另外,测试中错误设置了contentType(MediaType.APPLICATION_JSON),下载图片的请求不需要这个类型,虽不是空响应的直接原因,但不符合实际请求场景。
修正后的测试代码
import org.springframework.http.MediaType; import java.io.ByteArrayInputStream; import java.nio.file.Files; import java.io.File; // ... @Test void testDownloadImg() throws IOException { File imageFile = new File("src/test/resources", "test.png"); // 一次性读取图片全部字节,确保获取完整内容 byte[] expectedContent = Files.readAllBytes(imageFile.toPath()); // 关键:每次调用Mock服务时返回新的ByteArrayInputStream实例 // 避免流被提前耗尽的问题 when(myMockImgService.getImageFile(id)).thenReturn(new ByteArrayInputStream(expectedContent)); mockMvc.perform( get(DOWNLOAD_URL) // 移除错误的APPLICATION_JSON,或设置为对应图片类型(如IMAGE_PNG) .contentType(MediaType.IMAGE_PNG)) .andExpect(status().isOk()) .andExpect(content().bytes(expectedContent)); }
修正说明
- 复用字节数组,返回新流实例:先将图片文件读取为字节数组,再通过
ByteArrayInputStream每次返回新的流对象,确保控制器能读取到完整的图片内容,解决流被提前耗尽的问题。 - 修正请求Content-Type:下载图片时不需要设置
APPLICATION_JSON,改为对应图片类型或直接移除该设置,让请求更符合实际业务场景。 - 可靠读取文件内容:使用
Files.readAllBytes()替代inputStream.available()+read()的方式,因为available()仅返回当前可读取的字节数,无法保证获取到文件的完整大小,可能导致读取不完整。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

