如何模拟单元测试的标准包函数



我有三个函数:

func IsSymlinks(path string) {
...
...
}
func (c *MyClass) myFunc1(path string) {
...more code
...more code
if IsSymlinks(path) {
realPath := filepath.EvalSymlinks(path)
}
...more code
...more code
}
func myFunc2(path string) {
...more code
...more code
if IsSymlinks(path) {
realPath := filepath.EvalSymlinks(path)
}
...more code
...more code
}

如何通过模拟文件路径来测试 myFunc1 和 myFunc2。EvalSymlinks 和 IsSymlinks?我搜索了一些帖子,看到了几个解决方案。

  1. 创建一个函数类型的 EvalSymlinks 变量,使用 filepath 初始化。EvalSymlinks,然后在测试包中,将其更改为我的实现。但是,我宁愿不使用这种方法。

  2. 传入文件路径。EvalSymlinks和IsSymlinks作为参数进入myFunc。我也不喜欢使用这种方式。

  3. 很多人都在谈论嘲笑使用界面。你能帮忙吗?还是另一种可以测试myFunc的方法?谢谢!

  4. 正在考虑的另一种选择是在我进行函数测试之前在操作系统中创建指向路径的符号链接,然后在测试后立即删除符号链接是否是一种很好的做法?

您可以使用接口来完成此操作。例如,假设您有一个名为 Linker 的接口:

type Linker interface {
IsSymlinks(path String)
}

现在,可以将链接器对象嵌入到调用IsSymlinks方法的函数中。

type MyClass struct {
Linker
}
func (p *MyClass) myFunc(path String) {
_ = p.Linker.IsSymlinks(path)
}

现在,在您的测试中,您可以创建一个模拟链接器。

type mockLinker struct{}
//implement the IsSymlinks on the mockLinker as you wish
p := &MyClass{
Linker: mockLinker,
}
p.myFunc(path)

p.myFunc到达IsSymlinks方法时,它会调用模拟IsSymlinks方法。

对于filepath.EvalSymlinks(path),您可以将该方法包装在您的另一个方法中,并将新方法添加到同一接口并模拟该方法而不是模拟EvalSymlinks

仅出于测试目的创建接口可能并不总是最好的主意,因为在某些情况下可能会导致大型接口在 Go 中不是惯用的,因为它会使代码的可读性降低。

我认为您可以尝试以不同的方式设计MyClass结构和相关函数。我的意思是从像filepath这样的包中独立获取MyClass对象。首先,创建一个具有两个功能的新接口:

type MyEvalLink interface {
IsSymlinks(path string) bool
EvalSymlinks(path string) (string, error)
}

然后,您可以在使用 filepath 包或假代码的结构中实现这两个函数:

type EvalLinkUse struct{}
func (p *EvalLinkUse) IsSymlinks(path string) bool {
// put here your real code or fake
}
func (p *EvalLinkUse) EvalSymlinks(path string) (string, error) {
// put here your real code or fake
}

因此,您的代码将更改如下:

type MyClass struct {
...your code
MyEvalLink MyEvalLink
} 

func (c *MyClass) myFunc1(path string) {
...more code
...more code
if c.MyEvalLink.IsSymlinks(path) {
realPath := c.MyEvalLink.EvalSymlinks(path)
}
...more code
...more code
}

这适合你的情况吗?

最新更新