我正在尝试测试以下分支:
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
continue
}
return errors.File().AddDetails(err)
}
很显然,如果os.Stat
不存在,path
将引发错误。 Reading the Golang documentation不返回有关os.Stat
可能返回的错误的详细信息。有办法让os.Stat
引发另一种错误吗?
答案 0 :(得分:2)
您可能会导致错误,例如通过传递无效的文件名 IsNotExist
返回 false。
package main
import (
"fmt"
"os"
)
func main() {
_, err := os.Stat("\000x")
fmt.Println(err)
// prints:
//
// stat x: invalid argument
}
\000 (ASCII: NUL)
是 unix 文件名中的无效字符。
答案 1 :(得分:1)
我认为您会发现很难os.Stat
以与单元测试无关的平台方式控制抛出什么错误以及何时发生错误。如果您确实需要测试返回未知错误类型的路径,那么最好的选择是重构软件包代码,以便模拟os.Stat
。尽管您不能直接更改os.Stat
的行为,但是通过利用Go具有一流的功能这一事实,您可以使用一些间接的方式来对它进行模拟,而对代码的更改却很少。如果您的软件包代码如下所示:
package mypackage
import "os"
...
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
continue
}
return errors.File().AddDetails(err)
}
...
尝试对其进行重构,以使用分配给os.Stat
的未导出的软件包作用域函数变量:
package mypackage
import "os"
var osStat = os.Stat
...
if _, err := osStat(path); err != nil {
if os.IsNotExist(err) {
continue
}
return errors.File().AddDetails(err)
}
...
现在,在测试代码中(应该与被测试的代码位于相同的程序包中),您可以将osStat
重新分配给具有相同签名的任何函数以对其进行模拟:
package mypackage
import (
"os"
"testing"
)
func TestNotExistError(t *testing.T) {
osStat = func(string) (os.FileInfo, error) {
return nil, os.ErrNotExist
}
// in case other test functions depend on the unmocked behavior
defer func() {
osStat = os.Stat
}()
// rest of the test which triggers the codepath above
}
func TestOtherError(t *testing.T) {
osStat = func(string) (os.FileInfo, error) {
return nil, os.ErrInvalid
}
// in case other test functions depend on the unmocked behavior
defer func() {
osStat = os.Stat
}()
// rest of the test which triggers the codepath above
}
...