为归档函数 fs 创建单元测试

Create unit test for archive function fs

我有以下功能,按预期工作。现在我想为它创建单元测试。问题是我正在使用文件系统,但我无法弄清楚如何使用一些模拟或任何其他解决方案来做到这一点。知道如何在 Go 中简单地完成这件事吗? 我真的应该创建一个文件然后用单元测试检查吗?恐怕在某些系统中它会工作而有些它会损坏 (winodos/ mac/linux)

这是工作函数:

func Zipper(src string,artifact string,target string) error {

    zf, err := os.Create(artifact)
    if err != nil {
        return err
    }
    defer zf.Close()

    ziper := zip.NewWriter(zf)
    defer ziper.Close()

    fileInfo, err := os.Stat(src)
    if err != nil {
        return err
    }

    var bs string
    if fileInfo.IsDir(); len(target) > 0 {
        bs = target
    } else {
        bs = filepath.Base(src)
    }

    if bs != "" {
        bs += "/"
    }

    filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        if info.IsDir() {
            return nil
        }

        header, err := zip.FileInfoHeader(info)
        if err != nil {
            return err
        }

        if bs != "" {
            header.Name = filepath.Join(strings.TrimPrefix(path, bs))
        }

        header.Method = zip.Deflate

        writer, err := ziper.CreateHeader(header)
        if err != nil {
            return err
        }

        file, err := os.Open(path)
        if err != nil {
            return err
        }
        defer file.Close()
        _, err = io.Copy(writer, file)
        return err
    })

    return err
}

我阅读了以下内容,但对我的情况帮助不大 How to mock/abstract filesystem in go?

测试依赖于文件系统的功能的最简单方法是在每个测试周围添加一些设置和拆卸,在 运行 测试之前将必要的文件放在适当的位置,然后在 运行 测试后删除它们。

func TestZipper(t *testing.T) {
    // Create temporary files
    defer func() {
        // Clean up temporary files
    }()
    t.Run("group", func(t *testing.T) { // This is necessary so the above defer function doesn't run too soon
        // your actual tests
    })
}

我知道 "doesn't access the file system" 是很多人对 "unit test" 的定义的一部分。如果您的职业不是 寻找和捍卫定义:忘掉那个限制吧。文件系统访问快速且良好,go 工具甚至对名为 "testdata" 的文件夹进行特殊处理:此类文件夹应该包含测试期间要使用的测试数据。

Go(和他们的用户)在区分 "unit" 和 "integration" 测试时不是很迂腐。看看如何测试这些东西的标准库。编写相关测试比在 fs 访问上变得幼稚更重要。 (请注意,文件系统和数据库在技术上是外部系统,但在现实生活中,没有文件系统就无法编译 Go 代码,因此将测试与此隔离"external system" 是荒谬的。)

好吧,您可能会寻找一种以安全方式操作文件系统的方法,或者在其他地方寻找解决方案。这个功能的职责是什么?它应该准备一个 zip 文件还是将其写入文件系统?

我建议你把创建文件的功能去掉,改成:

func Zipper(src string, dst io.Writer, target string) error {
    ziper := zip.NewWriter(dst)
    defer ziper.Close()

这样,为了测试目的,您可以提供一个简单的缓冲区,而在生产中使用您钟爱的文件系统!