Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何为单元测试模拟标准包函数_Unit Testing_Go - Fatal编程技术网

Unit testing 如何为单元测试模拟标准包函数

Unit testing 如何为单元测试模拟标准包函数,unit-testing,go,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

我有三个职能:

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
    }
type MyEvalLink interface {
    IsSymlinks(path string) bool
    EvalSymlinks(path string) (string, error)
}
如何通过模拟filepath.EvalSymlinks和IsSymlinks来测试myFunc1和myFunc2?我搜索了一些帖子,发现了一些解决方案

  • 创建一个函数类型的EvalSymlinks变量,用filepath.EvalSymlinks初始化,然后在测试包中,将其更改为my implementation。然而,我不喜欢使用这种方法

  • 将filepath.EvalSymlinks和IsSymlinks作为参数传入myFunc。我也不想用这种方式

  • 很多人都在谈论模仿用户界面。你能帮忙吗?还是另一种可以测试myFunc的方法?谢谢大家!

  • 我想的另一个选择是,在我进行功能测试之前,在操作系统中创建一个指向路径的符号链接,然后在测试之后立即删除该符号链接,这是否是一种好的做法


  • 您可以通过使用一个接口来实现这一点。例如,假设您有一个名为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
    方法

    type MyClass struct {
        Linker
    }
    
    func (p *MyClass) myFunc(path String) {
        _ = p.Linker.IsSymlinks(path)
    }
    
    对于
    filepath.EvalSymlinks(path)
    您可以将该方法包装到您的另一个方法中,并将新方法添加到同一接口中,模拟该方法,而不是模拟
    EvalSymlinks


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

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

    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
        }
    
    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
    }
    

    这适合您的情况吗?

    非常感谢您的解决方案!我完全同意你的最后一段。我在另一篇文章中看到了类似的想法,我犹豫是否使用它,因为说服自己在MyClass中添加另一个字段只是为了测试两个小函数有点困难。我想看看是否还有其他解决办法。如果没有,我将采用这种接口方法。再次感谢你!由于我更新了我的问题,上述答案可能不容易适用于我的案例。我认为没有任何方法可以测试新的
    IsSymlinks
    函数,因为它不再是一种方法。我能想到的唯一方法是,如果
    IsSymlinks
    中的核心功能是全局对象上可以模拟的方法。接口通常应在对象可能发生变化但行为相同的情况下使用。如果是这种情况,那么接口就是正确的方法。您的选项#4可以使用,只要测试不会变得不稳定,例如,在测试运行之前尚未创建符号链接,或者在测试运行之后未正确删除符号链接。谢谢!我知道它适用于myFun1,但我不确定如何使用它来测试myFunc2,因为它不是任何类的一部分。谢谢!在操场上,我的理解是为了用MyClass中的Evalinkuse测试myFunc3,在测试中,我需要创建另一个函数(myFunc2),用MockEvalinkuse替换Evalinkuse。如果我的理解是正确的,我不希望重复代码(myFunc2)。此外,MyClass是一个大型结构,我不确定只使用其中两个函数创建它是否是一个好的实践(很抱歉,我是新手)。我同意你的观点,DRY(不要重复你自己)是一个很好的经验法则。去支持组合而不是继承,我用了很长时间,也许其他人可以建议一个更好的解决方案。