如何为Service层调用MultipartFile.transferTo()的方法编写Mockito测试
实现方案分两类,你可以根据测试场景选择
方案1:纯Mockito单元测试(无真实IO,执行速度快,符合单元测试规范)
这个方案不需要生成真实文件,只需要验证方法逻辑的正确性:路径拼接符合预期、transferTo方法被正确调用。
推荐先对原有代码做少量可测试性优化(也可以用静态mock跳过改造,改造后代码可维护性更高):
第一步:调整原Service代码
@Service public class FileService { // 从配置文件注入,测试时可手动赋值固定值 @Value("${file.golden.location}") private String goldenFileLocation; public void saveFile(MultipartFile file , int id) throws IOException { String date = generateTimeSuffix(); String destination = goldenFileLocation + "/" + file.getOriginalFilename() + date; file.transferTo(new File(destination)); } // 抽成protected方法,测试时可mock返回固定值 protected String generateTimeSuffix() { return LocalDateTime.now().format(DateTimeFormatter.ofPattern("-yyMMddHHmmss")); } }
第二步:编写Mockito测试代码
@ExtendWith(MockitoExtension.class) public class FileServiceTest { // spy用于mock内部的generateTimeSuffix方法 @Spy private FileService fileService; @Mock private MultipartFile mockFile; @Test public void testSaveFile() throws IOException { // 1. 构造测试固定参数 String testGoldenPath = "/test/golden"; String fixedTimeSuffix = "-240520131400"; String originalFileName = "response.pdf"; String expectedPath = testGoldenPath + "/" + originalFileName + fixedTimeSuffix; // 反射给goldenFileLocation赋值测试固定值 ReflectionTestUtils.setField(fileService, "goldenFileLocation", testGoldenPath); // mock返回固定的时间后缀 doReturn(fixedTimeSuffix).when(fileService).generateTimeSuffix(); // mock文件返回固定原始文件名 when(mockFile.getOriginalFilename()).thenReturn(originalFileName); // 2. 执行测试方法 fileService.saveFile(mockFile, 1); // 3. 验证transferTo方法传入的路径符合预期 verify(mockFile).transferTo(argThat(file -> expectedPath.equals(file.getAbsolutePath()))); } }
如果不想改原业务代码,可以用Mockito的静态mock能力 mock LocalDateTime.now()的返回值,不需要单独抽取时间生成方法。
方案2:验证真实文件存储(集成测试场景)
如果需要确认文件真的被写入磁盘,可以用JUnit 5的@TempDir注解创建临时目录,测试结束后自动清理,不会产生垃圾文件:
@ExtendWith(MockitoExtension.class) public class FileServiceTest { @InjectMocks private FileService fileService; // JUnit自动管理临时目录,测试结束自动删除 @TempDir private Path tempDir; @Test public void testSaveFileRealFile() throws IOException { // 1. 把临时目录设为存储路径 ReflectionTestUtils.setField(fileService, "goldenFileLocation", tempDir.toString()); // 构造测试文件 byte[] fileContent = "data".getBytes(); MockMultipartFile firstFile = new MockMultipartFile("pdf", "response.pdf", "multipart/form-data", fileContent); // 2. 执行测试方法 fileService.saveFile(firstFile,1); // 3. 验证文件存在且内容正确 Optional<Path> savedFile = Files.list(tempDir) .filter(path -> path.getFileName().toString().startsWith("response.pdf-")) .findFirst(); // 验证文件存在 assertTrue(savedFile.isPresent()); // 验证文件内容和写入内容一致 assertArrayEquals(fileContent, Files.readAllBytes(savedFile.get())); } }
内容的提问来源于stack exchange,提问作者Neha Modi
相关产品推荐
相关产品推荐

