【发布时间】:2021-09-30 07:32:44
【问题描述】:
假设我有一个包含以下代码的包:
package paths
type FilePath struct {
PathA string
}
func (c FilePath) GetPathA() string {
if err := PathExists(PathA); err != nil {
return ""
}
return PathA + "foo"
}
func PathExists(p string) error {
// call os and file methods
return err
}
如何模拟 PathExists 依赖项来测试 FilePath?此外,许多其他软件包也正在使用方法PathExists。 (我愿意接受重构它以使其测试友好的建议,请牢记以下几点)
我遇到了几种不同的方法,但对我来说,它们都不直观或惯用。
-
包中有一个全局变量
PE := PathExists;在GetPathA中,调用err := PE(PathA)并在测试中使用模拟方法覆盖PE。问题:如果测试包类似于paths_test,我将不得不导出
PE,这样包的客户端也可以覆盖它。 -
将
PathExists设为FilePath的字段并在测试中模拟该字段。问题:客户在使用包时,必须初始化
PathExists字段,或者我提供NewFilePath(PathtA string)形式的构造函数,它为我初始化字段。在实际用例中有很多字段,因此这种方法也失败了。 -
使用接口并将其嵌入到结构中。当客户端使用它时,使用实际方法初始化并进行测试模拟它。
type PathExistser interface{ PathExists(p string) error } type FilePath struct{ PathA string PathExister } type Actual struct{} func (a Actual) PathExists(p string) error { return PathExists(p) }问题:客户端再次需要提供正确的接口实现。
我学到了一些与上述选项类似的方法,例如将方法 PathExists 作为 GetPathA 的参数等。所有这些都有相同的问题。基本上,我不希望这个包的用户必须弄清楚什么应该是正确的输入参数来确保结构按预期工作。我也不希望用户覆盖PathExists 的行为。
这似乎是一个非常简单的问题,我似乎遗漏了一些关于 go 测试或模拟的非常重要的东西。任何帮助将不胜感激,谢谢。
方法名称只是举例。实际上GetPathA 或PathExists 会更复杂。
【问题讨论】:
标签: unit-testing go testing mocking