英文:
How do you test filepath.Abs failure in your Golang code?
问题
在我的Go代码中,我不得不多次使用filepath.Abs(),这可能会导致我的方法返回不同的错误。
func (s *service) myFunc(path string) error {
dir := s.Component().Dir()
absDir, err := filepath.Abs(dir)
if err != nil {
return my_errors.NewFailedToGetAbsoluteComponentDir()
}
absPath, err := filepath.Abs(path)
if absPath != nil {
return my_errors.NewFailedToGetAbsPath()
}
// 更多代码...
return nil
}
在我的单元测试中,我想要测试它,但我唯一能想到的方法是将filepath.Abs作为一个依赖注入到我的结构体中。
还有其他我没有考虑到的方法吗?
或者你认为这种测试是不必要的吗?
英文:
In my Go code, I have to use filepath.Abs() several times, which may lead to different errors that my method returns.
func (s *service) myFunc(path string) error {
dir := s.Component().Dir()
absDir, err := filepath.Abs(dir)
if err != nil {
return my_errors.NewFailedToGetAbsoluteComponentDir()
}
absPath, err := filepath.Abs(path)
if absPath != nil {
return my_errors.NewFailedToGetAbsPath()
}
// more code...
return nil
}
In my unit test, I want to test it, but the only way I can think of is to inject filepath.Abs as a dependency into my struct.
Is there any other way I did not think of?
Or do you think that this kind of test is unnecessary?
答案1
得分: 4
如果我们查看标准库中filepath.Abs
函数的源代码,我们可以看到它在返回错误时的情况,然后尝试在我们的测试中触发该条件。filepath.Abs
根据编译的目标操作系统的不同有不同的实现,但是例如Unix实现看起来像这样:
func unixAbs(path string) (string, error) {
if IsAbs(path) {
return Clean(path), nil
}
wd, err := os.Getwd()
if err != nil {
return "", err
}
return Join(wd, path), nil
}
因此,它只会在os.Getwd()
返回错误时才返回错误。让os.Getwd()
返回错误的一种简单方法是确保当前工作目录不存在。可以在测试中这样做:
dir, _ := os.MkdirTemp("", "") // 创建一个临时目录
os.Chdir(dir) // 切换到该目录
os.RemoveAll(dir) // 删除该目录
fmt.Println(os.Getwd()) // 现在将返回一个错误
现在这个方法的问题是它会改变整个进程的工作目录,这可能会干扰其他测试。因此,重要的是在此测试运行后重置工作目录,并确保不同时运行依赖于工作目录的其他测试。
要重置工作目录,在测试开始时添加以下代码:
origWd, _ := os.Getwd()
t.Cleanup(func() {
os.Chdir(origWd)
})
并且为了确保没有其他冲突的测试同时运行,在测试中不要调用t.Parallel()
。
这是否值得测试呢?通常不值得。你的工作目录有多少可能是无效的?在大多数情况下,几乎不可能。如果是这种情况,我建议不要测试代码的这部分。
然而,如果你正在构建一个命令行工具,工作目录经常变化或者常常是未知的,那么这样的测试可能确实是值得的。
在你付出这么多努力之前,请确保你的测试提供了一些实际价值
我制作了一个视频讨论这个问题,以及对该主题感兴趣的任何人的一般问题:回答StackOverflow:如何测试Go中的filepath.Abs?
英文:
If we look at the source code for the filepath.Abs
function in the standard library, we can see when it returns an error, and then try to trigger that condition in our tests. filepath.Abs
has different implementations depending on which target OS it's compiled for, but the Unix implementation, for example, looks like this:
func unixAbs(path string) (string, error) {
if IsAbs(path) {
return Clean(path), nil
}
wd, err := os.Getwd()
if err != nil {
return "", err
}
return Join(wd, path), nil
}
So the only time it will ever return an error is when os.Getwd()
returns an error. An easy way to make os.Getwd()
return an error is to ensure that your current working directory doesn't exist. This can be done in a test as so:
dir, _ := os.MkdirTemp("", "") // Create a temporary directory
os.Chdir(dir) // Change to that directory
os.RemoveAll(dir) // Delete that directory
fmt.Println(os.Getwd()) // This will now return an error
Now this has the problem that it changes the working directory for the entire process, which could interfere with other tests. So it's important to both reset the working directory after this test runs, and also to make sure that no other tests that depend on the working directory run at the same time.
To reset it, put this at the beginning of your test:
origWd, _ := os.Getwd()
t.Cleanup(func() {
os.Chdir(origWd)
})
And to make sure no other conflicting tests run at the same time, don't call t.Parallel()
in your test.
<hr>
Is it worth it to test this? Usually not. How often is your working directory likely to be invalid? Under most circumstances, never. If that describes you, I simply wouldn't test this part of your code.
However, if you're building a CLI tool, for example, where the working directory is in constant flux or often unknown, then such a test may indeed be worth it.
Just make sure your test provides some actual value, before you go to this much effort
<hr>
I've made a video discussing this question, and the general question for anyone interested in a longer discussion of the topic: Answering StackOverflow: How do you test filepath.Abs in Go?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论