无法在我的程序和我的单元测试中使用相同的相对路径

时间:2015-08-13 13:59:36

标签: go

在我的Go项目中,我使用一个打开特定文件并返回其内容的函数。该文件存储在另一个目录中,但仍在我的项目目录中。

package infrastructure

func openKey() ([]byte, error) {
    if path, err := filepath.Abs("../security/key.rsa"); err != nil {
        return nil, err
    } 

    return ioutil.ReadFile(path)
}

如果我从单元测试中调用它,则此功能有效。但是如果我在程序中调用相同的函数,我就会出现这个错误:

  

2015/08/13 15:47:54开放   /me/go/src/github.com/myaccount/security/key.rsa:没有这样的文件   或目录

文件的正确绝对路径是:

  

/me/go/src/github.com/myaccount/的 myrepo /security/key.rsa

使用openKey函数的代码(来自我的程序和单元测试)都在同一个包中:infrastructure

以下是我执行程序的方法:

  

go install&& ../../../../斌/ myproject的

我如何执行单元测试:

  

去测试./ ...

最后是我项目的目录结构:

go/src/github.com/myaccount/myrepo/: 
- main.go
- security:
    - key.rsa // The file that I want to open
    - ...
- infrastructure
    - openFile.go // The file with the func `openKey``
    - server.go // The file with the func that call the func `openKey`
    - openFile_test.go // The unit test that calls the func `openKey`

修改:

以下是程序二进制文件所在的绝对路径:

  

/用户/我/文档/Développement公司/吉恩/去/ bin中

我的单元测试位于:

  

/var/folders/tj/8ywtc7pj3rs_j0y6zzldwh5h0000gn/T/go-build221890578/github.com/myaccount/myrepo/infrastructure/_test

有什么建议吗? 谢谢!

2 个答案:

答案 0 :(得分:4)

首先,在运行测试时,不应使用与在生产环境中运行应用程序时相同的文件。因为有权访问存储库的每个人都可以访问测试文件,这是一个安全性失败。

如评论中所述,问题在于,在运行测试时,工作目录是这些源代码(实际上,在运行测试之前将整个数据集复制到临时目录中),而当你运行测试时运行程序为real,工作目录是你运行命令的目录,因此错误的相对路径。

我建议使用配置选项来获取加载文件的文件(或用于路径的基本目录)。使用环境变量(我强烈建议您这样做,有关详细信息,请参阅12factors manofesto),配置文件,命令行标志等。

答案 1 :(得分:-1)

go test ./...命令在运行该目录中的测试之前将当前目录更改为go/src/github.com/myaccount/myrepo/infrastructure。因此,测试中的所有相对路径都与infrastructure目录相关。

允许测试的简单,可靠的方法是更改​​函数的签名。

func openKey(relPath string) ([]byte, error) {
    if path, err := filepath.Abs(relPath); err != nil {
        return nil, err
    } 

    return ioutil.ReadFile(path)
}

这使您可以自由地在测试期间将key.rsa放置在任何位置,例如,您可以复制它并将其存储在infrastructure

更优雅,更健壮的方式是使用io.Reader

func openKey(keyFile io.Reader) ([]byte, error) {
    return ioutil.ReadAll(keyFile)
}

因为你可以传递strings.Reader进行测试。这意味着您可以测试代码而无需依赖文件系统。但在这种情况下,这可能有点过头了。