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

如何对使用Java NIO Files库的文件操作方法进行单元测试

单元测试方案

这里提供两个可行的测试方案,优先推荐JimFS内存文件系统方案,更贴近真实执行逻辑,测试结果可信度更高。

前置优化建议

先对原方法做两个小优化,既提升代码健壮性也更便于测试:

  • 调整空指针判断顺序:把target != null的判断放到Files.notExists(target)前面,避免target为null时触发空指针异常
  • 建议将path1、path2、fileToRead三个变量通过方法参数或者类构造方法注入,不要硬编码在类中,方便测试时传入自定义路径

方案1:JimFS内存文件系统测试(推荐)

JimFS是Google开源的内存文件系统,不需要操作本地磁盘,执行速度快,能真实模拟文件操作的全流程,可直接验证方法执行结果是否符合预期。

依赖引入

Maven坐标:

<dependency>
    <groupId>com.google.jimfs</groupId>
    <artifactId>jimfs</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>

测试代码示例(JUnit5)

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

public class FileUtilTest {
    private FileSystem jimfs;
    private Path sourcePath;
    private Path targetPath;
    private final String testListFileName = "file_list.txt";
    private final List<String> testFileList = List.of("a.txt", "b.jpg", "c.json");

    @BeforeEach
    void initTestEnv() throws Exception {
        // 初始化内存文件系统
        jimfs = Jimfs.newFileSystem(Configuration.unix());
        sourcePath = jimfs.getPath("/test/source");
        targetPath = jimfs.getPath("/test/target");
        Files.createDirectories(sourcePath);

        // 构造源目录测试数据
        // 1. 写入待读取的文件列表
        Files.write(sourcePath.resolve(testListFileName), testFileList, StandardCharsets.UTF_8);
        // 2. 创建列表内的所有测试文件,写入测试内容
        for (String fileName : testFileList) {
            Files.writeString(sourcePath.resolve(fileName), "test content for " + fileName);
        }
    }

    @AfterEach
    void clearTestEnv() throws Exception {
        jimfs.close();
    }

    @Test
    void testCopyAndMoveFiles() throws Exception {
        // 初始化业务类,注入测试用的路径参数
        YourService yourService = new YourService();
        yourService.setPath1(sourcePath.toString());
        yourService.setPath2(targetPath.toString());
        yourService.setFileToRead(testListFileName);

        // 执行待测试方法
        yourService.copyAndMoveFiles();

        // 断言验证执行结果
        // 1. 目标目录已成功创建
        assertTrue(Files.exists(targetPath));
        // 2. 所有列表内的文件都已复制到目标目录,且内容和源文件一致
        for (String fileName : testFileList) {
            Path targetFile = targetPath.resolve(fileName);
            assertTrue(Files.exists(targetFile));
            assertEquals("test content for " + fileName, Files.readString(targetFile));
        }
    }
}

方案2:Mockito静态方法Mock(行为验证)

如果不想引入额外依赖,使用Mockito 3.4及以上版本支持的静态类Mock能力,验证Files相关方法的调用行为是否符合预期即可。

测试代码示例

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import static org.mockito.Mockito.*;

public class FileUtilTest {
    private final String path1 = "/test/source";
    private final String path2 = "/test/target";
    private final String testListFileName = "file_list.txt";
    private final List<String> testFileList = List.of("a.txt", "b.jpg");

    @Test
    void testCopyAndMoveFiles() throws Exception {
        try (MockedStatic<Files> mockedFiles = mockStatic(Files.class);
             MockedStatic<Paths> mockedPaths = mockStatic(Paths.class)) {
            Path source = mock(Path.class);
            Path target = mock(Path.class);
            Path listFile = mock(Path.class);

            // 打桩静态方法返回值
            mockedPaths.when(() -> Paths.get(path1)).thenReturn(source);
            mockedPaths.when(() -> Paths.get(path2)).thenReturn(target);
            mockedFiles.when(() -> Files.notExists(target)).thenReturn(true);
            when(source.resolve(testListFileName)).thenReturn(listFile);
            mockedFiles.when(() -> Files.readAllLines(listFile)).thenReturn(testFileList);

            // 初始化业务类,设置参数
            YourService yourService = new YourService();
            yourService.setPath1(path1);
            yourService.setPath2(path2);
            yourService.setFileToRead(testListFileName);

            // 执行待测试方法
            yourService.copyAndMoveFiles();

            // 验证方法调用行为符合预期
            // 验证目标目录创建方法被调用1次
            mockedFiles.verify(() -> Files.createDirectories(any()), times(1));
            // 验证每个文件都执行了复制操作
            for (String fileName : testFileList) {
                Path sourceFile = mock(Path.class);
                Path targetFile = mock(Path.class);
                when(source.resolve(fileName)).thenReturn(sourceFile);
                when(target.resolve(fileName)).thenReturn(targetFile);
                mockedFiles.verify(() -> Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING), times(1));
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:36:02