【问题标题】:Mocking method from golang packagegolang包中的模拟方法
【发布时间】:2016-03-07 17:21:23
【问题描述】:

我一直无法从 golang 包中找到模拟方法的解决方案。

例如,我的项目中有代码会在 Os.Getwd() 返回错误时尝试恢复。我能想到为此进行单元测试的最简单方法是模拟 Os.Getwd() 方法以返回错误,并验证代码是否相应地工作。

我尝试使用 testify,但似乎不可能。

有人有这方面的经验吗?

【问题讨论】:

    标签: unit-testing go mocking testify


    【解决方案1】:

    我自己的解决方案是将方法作为参数,它允许在测试时注入“模拟”。另外,创建一个导出的方法作为公共外观和一个未导出的用于测试。

    例子:

        func Foo() int {        
                return foo(os.Getpid)
        }                       
    
        func foo(getpid func() int) int {
                return getpid()      
        } 
    

    【讨论】:

    • 谢谢,这似乎是一种方法,但希望有一种更简单的方法可以在测试期间创建模拟方法
    • 好吧,由于它的静态类型性质,go 中的 mock 与其他语言(例如 PHP)相比非常原始,所以就 mock 而言,我不知道其他解决方案.不过,可能有一个我不知道的聪明把戏。
    • 另一个解决方案是@sargas 回答,一旦我开始广泛使用文件,它就成为我的做法:我创建了一个test 目录,其中包含我知道的状态下的一堆文件,我知道这些文件会成为我的方法想要失败。在处理文件系统时,我倾向于发现这要简单得多……
    • 这是唯一一种可能的模拟解决方案,但它很糟糕,就像所有 go 语言设计一样糟糕。
    【解决方案2】:

    看起来,看看os.Getwd test 可以为您提供一些如何测试代码的示例。查找函数TestChdirAndGetwdTestProgWideChdir

    通过阅读这些内容,测试似乎创建了临时文件夹。

    因此,一种实用的方法是创建临时文件夹,就像上面提到的测试一样,然后破坏它们,以便 os.Getwd 抛出一个错误,以便您在测试中捕捉到。

    请小心执行这些操作,因为它们会弄乱您的系统。我建议在轻量级容器或虚拟机中进行测试。

    【讨论】:

    • 这实际上不是testing,这只是在环境中跳舞以寻找可能的错误。嘲笑环境不会重现所有可能的测试用例。
    【解决方案3】:

    我知道这有点晚了,但是你可以这样做。

    测试 DAL 或 SystemCalls 或包调用通常很困难。我解决这个问题的方法是将你的系统函数调用推到接口后面,然后模拟这些接口的函数。例如。

    type SystemCalls interface {
     Getwd() error
    }
    
    
    type SystemCallsImplementation struct{
    }
    func (SystemCallsImplementation) Getwd() error{
     return  Os.Getwd() 
    }
    
    func MyFunc(sysCall SystemCalls) error{
    
    sysCall.Getwd()
    }
    

    通过这个,您可以注入您的接口,该接口具有对您的函数的系统调用。现在您可以轻松地为您的接口创建一个模拟实现以进行测试。

    喜欢

    type MockSystemCallsImplementation struct{
    err error
    }
    func (MockSystemCallsImplementation) Getwd() error{
    return err  //this can be set to nil or some value in your test function
    }
    

    希望这能回答你的问题。

    【讨论】:

    • 无法使用此方法测试package(如os),因为在 go 中无法将包作为参数传递。所以你必须将你的接口实现(os 的包装器)包含到应用程序的发布版本中。这太糟糕了,任何人都不应该使用它。
    • 我并不是说我们可以使用这种方法测试系统调用,我们可以通过将系统调用放在接口后面来测试其他功能。这正是你所说的
    【解决方案4】:

    这是 go 编译器的限制,google 开发者不希望允许任何钩子或猴子补丁。如果单元测试对你很重要——那么你必须选择一种源代码中毒的方法。所有这些方法如下:

    • 您不能直接使用全局包。
    • 您必须创建独立版本的方法并对其进行测试。
    • 生产版本的方法包括隔离版本的方法和全局包。

    但最好的解决方案是完全忽略 Go 语言(如果可能的话)。

    【讨论】:

      猜你喜欢
      • 2017-09-29
      • 1970-01-01
      • 2017-08-07
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      • 2015-04-09
      • 2015-07-17
      • 2018-03-14
      相关资源
      最近更新 更多