是否可以在golang中模拟从包中导入的函数?

时间:2017-03-22 12:52:20

标签: unit-testing testing go mocking

我有以下测试方法,它使用从包中导入的函数。

import x.y.z

func abc() {
    ...
    v := z.SomeFunc()
    ... 
}

是否可以在golang中模拟SomeFunc()

4 个答案:

答案 0 :(得分:20)

是的,通过简单的重构。创建一个zSomeFunc函数类型的变量,使用z.SomeFunc进行初始化,然后让您的包调用而不是z.SomeFunc()

var zSomeFunc = z.SomeFunc

func abc() {
    // ...
    v := zSomeFunc()
    // ...
}

在测试中,您可以为zSomeFunc分配另一个函数,一个在测试中定义的函数,并执行测试所需的任何函数。

例如:

func TestAbc(t *testing.T) {
    // Save current function and restore at the end:
    old := zSomeFunc
    defer func() { zSomeFunc = old }()

    zSomeFunc = func() int {
        // This will be called, do whatever you want to,
        // return whatever you want to
        return 1
    }

    // Call the tested function
    abc()

    // Check expected behavior
}

查看相关/可能重复: Testing os.Exit scenarios in Go with coverage information (coveralls.io/Goveralls)

答案 1 :(得分:6)

你可以做的一件事是:

import x.y.z

var someFunc = z.SomeFunc

func abc() {
    ...
    v := someFunc
    ... 
}

在你的测试文件中,你会这样做。

func Test_abc() {
    someFunc = mockFunc
    abc()
}

但请确保以并发方式执行此操作,如果您有多个TestXxx函数调用abc或设置someFunc,则可能更适合使用struct使用someFunc字段。

答案 2 :(得分:2)

有功能指针和猴子修补它是这样做的。但是当你使用多个函数进行模拟时,你将拥有一个数字函数指针,不必要的是你只需要使用函数指针来调用函数。

更好和推荐的想法是拥有一个接口并使你的函数成为实现接口的struct的一部分。完成后,您可以使用一些可用的好工具生成模拟。

我一直在用这个:

mockgen -source myModule.go -package myPackage -destination myModuleMock.go

您可以通过以下方式安装:

got get github.com/golang/mock

答案 3 :(得分:0)

public function getDuration(){ $start = $this->created_at; $end = now(); return $end->diff($start)->format('%H:%S'); } 使用一种允许您生成模拟类的方法,您可以指示 mockcompose 包含您选择的依赖项闭包(从其他包中导入的任何函数)。同时,它会生成具有本地覆盖的主题函数的克隆副本,以便您可以对其进行测试。您可以使用 mockcompose 嵌入代码生成过程,从而确保您的克隆副本始终与您的代码更改同步。

假设您有一个函数 go generate functionThatUsesGlobalFunction 在包 Sprintf 中。

fmt

您的目标是使用 func functionThatUsesGlobalFunction( format string, args ...interface{}, ) string { // // skip fansy logic... // // call out to a global function in fmt package return fmt.Sprintf(format, args...) } 包中的 functionThatUsesGlobalFunction 被模拟来测试 Sprintf

为此,您可以将 fmt 配置为 go generate,如下所示:

mocks.go

mockcompose

//go:generate mockcompose -n mockFmt -p fmt -mock Sprintf //go:generate mockcompose -n mockJson -p encoding/json -mock Marshal //go:generate mockcompose -n clonedFuncs -real "functionThatUsesGlobalFunction,fmt=fmtMock" package clonefn 然后将为您生成管道类,使您能够编写如下测试代码:

go generate mockcompose

请查看this了解详情。