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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 18:06:04