Golang测试文件扫描函数时使用临时目录是否为合理实践?
两种测试方案的优劣对比
临时目录测试方案完全合理
这是IO类函数测试的主流实践,优势非常明显:
- 完全不侵入业务代码,不需要修改原有
FileScan函数的签名和实现,避免测试逻辑带来的额外风险 - 测试覆盖的是函数完整的真实执行链路,包括路径拼接、目录读取、权限校验等逻辑都能被覆盖,不会出现Mock和真实运行环境行为不一致导致的测试漏判
- Go标准库已经提供了
testing.T.TempDir()工具方法,会自动创建系统临时目录,且测试结束后自动清理,连你自己写defer删除的逻辑都不需要,使用成本很低 - 仅有的缺点是测试速度比纯内存Mock略慢,但只要测试用的目录结构不是特别复杂,性能损耗可以忽略不计
Mock FileInfo方案不是更优选择
这种方案适合的场景非常有限,不建议作为首选:
- 首先需要修改原有函数的入参签名,属于测试逻辑侵入业务代码的行为,对于已经成型的业务函数来说改造成本高,还可能影响其他调用方
- 就算修改了入参,你也只能Mock文件元数据,函数内部的
ioutil.ReadDir调用、路径拼接逻辑依然覆盖不到,比如你现有代码里用fmt.Sprintf("%s/%s", dir, file.Name())拼接路径的写法在Windows平台会出问题,这类问题Mock测试完全发现不了 - 只有当你需要测试一些本地很难构造的极端边界场景(比如特殊权限位、异常字符文件名)时,才适合单独抽离核心分类逻辑做Mock测试
额外优化建议
你现有代码的路径拼接逻辑可以优化,替换为filepath.Join(dir, file.Name()),可以兼容不同操作系统的路径分隔符,避免跨平台运行错误。临时目录测试的示例写法参考:
import ( "testing" "os" "path/filepath" ) func TestFileScan(t *testing.T) { // 自动创建临时目录,测试结束自动清理 tempDir := t.TempDir() // 构造测试目录结构 // 创建子目录dir1,放入a.txt、b.txt subDir1 := filepath.Join(tempDir, "dir1") if err := os.Mkdir(subDir1, 0755); err != nil { t.Fatalf("create test dir failed: %v", err) } os.Create(filepath.Join(subDir1, "a.txt")) os.Create(filepath.Join(subDir1, "b.txt")) // 创建子目录dir2,放入c.txt subDir2 := filepath.Join(tempDir, "dir2") if err := os.Mkdir(subDir2, 0755); err != nil { t.Fatalf("create test dir failed: %v", err) } os.Create(filepath.Join(subDir2, "c.txt")) // 执行测试 res, err := FileScan(tempDir) if err != nil { t.Fatalf("FileScan execute failed: %v", err) } // 结果校验 if len(res["dir1"]) != 2 || (res["dir1"][0] != "a.txt" && res["dir1"][1] != "a.txt") { t.Error("dir1 file list not match expected") } if len(res["dir2"]) != 1 || res["dir2"][0] != "c.txt" { t.Error("dir2 file list not match expected") } }
内容的提问来源于stack exchange,提问作者TheNoobGuy
相关产品推荐
相关产品推荐

