从Golang包中模仿的方法

cld4siwp  于 2023-11-14  发布在  Go
关注(0)|答案(5)|浏览(109)

我一直无法找到一个解决方案,从golang包模拟方法。
例如,我的项目中有一段代码试图在Os.Getwd()返回错误时进行恢复。我能想到的最简单的单元测试方法是模拟Os.Getwd()方法返回错误,并验证代码是否相应地工作。
我试着用了证明,但似乎不可能。
有人有这方面的经验吗?

vxf3dgd4

vxf3dgd41#

我自己的解决方案是将方法作为参数,这样可以在测试时注入一个“mock”。另外,创建一个导出的方法作为公共外观,并创建一个未导出的方法用于测试。
范例:

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

    func foo(getpid func() int) int {
            return getpid()      
    }

字符串

szqfcxe2

szqfcxe22#

我知道这有点晚,但这是你可以做的。
测试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
}


希望这能回答你的问题。

im9ewurl

im9ewurl3#

看起来看一下os.Getwd test可以给你给予一些如何测试代码的例子。查找函数TestChdirAndGetwdTestProgWideChdir
通过阅读这些文件,似乎测试创建了临时文件夹。
因此,一个实用的方法是创建临时文件夹,就像上面提到的测试一样,然后打破它们,这样os.Getwd就会抛出一个错误,让您在测试中捕捉到。
只是要小心做这些操作,因为它们可能会搞乱你的系统。我建议在轻量级容器或虚拟机中进行测试。

xienkqul

xienkqul4#

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

  • 不能直接使用全局包。
  • 你必须创建方法的隔离版本并测试它。
  • 方法的生产版本包括方法的隔离版本和全局包。

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

n3schb8v

n3schb8v5#

@Pharaoh上面的答案是最好的,特别是对于广泛的测试,因为它允许标准模拟提供的所有控制。
对于只需要模拟少量方法的简单情况和相当简单的情况,我使用以下方法,避免了创建新接口和使用标准调用实现该接口的包的需要。
在测试的实现中:

package myPackage

imports (...)

var (
    kill = syscall.Kill
    getCwd = os.GetCwd
)

字符串
在测试代码中:

// restore golang methods from "poor man's mocks"
func restore() {
    kill = syscall.Kill
    getWd = os.GetWd
}

func TestMyFunc(t *testing.T) {
    defer restore()

    // successful case
    kill = func(p int, s syscall.Signal) error {
        return nil
    }
    getWd = func() (string, error) {
        return "mywd", nil
    }
    err := MyFunc()
    assert.NoError(t, err)

    // error case for GetCwd
    getCwd = func(path string) (string, error) {
        return "", errors.New("test error")
    }
    err := MyFunc()
    assert.ErrorContains(t, "test error")
}

相关问题