用于单元测试的golang模拟标准包功能

时间:2018-07-08 02:46:41

标签: unit-testing go

更新我的问题:

我有以下三个功能:

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
    }

我的问题是如何通过模拟filepath.EvalSymlinks和IsSymlinks测试myFunc1和myFunc2?我搜索了一些帖子,并看到了几种解决方案。

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

  2. 将文件路径.EvalSymlinks和IsSymlinks传递给myFunc作为参数。我也不想使用这种方式。

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

  4. 我在考虑的另一种选择是,在执行功能测试之前,在os中创建到路径的符号链接,然后在测试之后立即删除符号链接是否是一种好习惯?

2 个答案:

答案 0 :(得分:1)

您可以通过使用界面来实现。例如,假设您有一个名为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中不习惯使用大型接口,因为这会使代码的可读性降低。

答案 1 :(得分:0)

我认为您可以尝试以其他方式设计MyClass结构和相关功能。我的意思是从文件路径之类的包中获得独立的MyClass对象。首先,创建一个具有两个功能的新界面:

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

然后,您可以在使用文件路径包或伪代码的结构中实现这两个功能:

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
}

适合您的情况吗?