GoMonkey单元测试框架


GoMonkey单元测试框架

GoMonkey 是一个用于 Go 语言单元测试的打桩框架,能够帮助开发者在不修改原始代码的情况下,对函数、方法等进行动态替换,以便更好地进行单元测试

由于方法(成员函数)无法通过 GoStub 框架打桩,当产品代码的 OO 设计比较多时,打桩点可能离被测函数比较远,导致UT用例写起来比较难受。同时过程或函数通过 GoStub 框架打桩时,对产品代码有侵入性。Gomonkey框架解决了这部分问题

Gomokey通过在运行时通过汇编语句重写可执行文件,将待打桩函数或方法的实现跳转到桩实现,原理和热补丁类似。通过 Monkey,我们可以解决函数或方法的打桩问题,但 Monkey 不是线程安全的,不要将 Monkey 用于并发的测试中。

安装

使用以下命令安装 GoMonkey:

go get github.com/agiledragon/gomonkey

对于 v2.1.0 及以上版本,例如 v2.11.0,使用以下命令:

go get github.com/agiledragon/gomonkey/v2@v2.11.0

基本使用

1. 为函数打桩

ApplyFunc

将目标函数 target 替换为自定义实现 double

patches := gomonkey.ApplyFunc(target, double)
defer patches.Reset()
  • target 表示要被替换的原始函数。
  • double 表示替换后的函数,用它来模拟原始函数的行为。

例如,将 SomeFunction 替换为返回固定值 42 的函数:

patches := gomonkey.ApplyFunc(SomeFunction, func(arg int) int {
    return 42
})
defer patches.Reset()

ApplyFuncReturn

将目标函数 target 替换为一个固定的返回值,而不需自定义函数逻辑。

patches := gomonkey.ApplyFuncReturn(target, output...)
defer patches.Reset()
  • target 表示要替换的目标函数。
  • output 是变参形式,表示目标函数的返回值,可以指定一个或多个返回值。

2. 为公共成员方法打桩

ApplyMethod

将目标类型的公共成员方法 methodName 替换为自定义实现 double

patches := gomonkey.ApplyMethod(reflect.TypeOf(receiver), methodName, double)
defer patches.Reset()
  • receiver 是方法的接收者类型。
  • methodName 是要替换的方法名称。
  • double 是替换后的函数。

例如,将 MyStructmyMethod 替换为返回 42 的函数:

type MyStruct struct{}
func (m *MyStruct) myMethod() int { return 10 }

patches := gomonkey.ApplyMethod(reflect.TypeOf(&MyStruct{}), "myMethod", func(_ *MyStruct) int {
    return 42
})
defer patches.Reset()

ApplyMethodReturn

将目标类型的公共成员方法 methodName 替换为固定的返回值。

patches := gomonkey.ApplyMethodReturn(reflect.TypeOf(receiver), methodName, output...)
defer patches.Reset()

3. 为私有成员方法打桩

ApplyPrivateMethod

将目标类型的私有成员方法 methodName 替换为自定义实现 double

patches := gomonkey.ApplyPrivateMethod(receiver, methodName, double)
defer patches.Reset()
  • receiver 是方法的接收者类型。
  • methodName 是要替换的方法名称。
  • double 是替换后的函数。

例如,将 MyStruct 的私有方法 myPrivateMethod 替换为返回 42 的函数:

type MyStruct struct{}
func (m *MyStruct) myPrivateMethod() int { return 10 }

patches := gomonkey.ApplyPrivateMethod(&MyStruct{}, "myPrivateMethod", func(_ *MyStruct) int {
    return 42
})
defer patches.Reset()

注意事项

  1. 关闭内联优化:GoMonkey 不支持内联函数,在测试时需要通过命令行参数 -gcflags=-l(Go 1.10 以下)或 -gcflags=all=-l(Go 1.10 及以上)关闭 Go 语言的内联优化
  2. 线程安全:GoMonkey 不是线程安全的,所以不要把它用到并发的单元测试中

示例

假设有一个函数 SomeFunction 和一个结构体 MyStruct,我们来演示如何为它们打桩。

package main

import (
    "fmt"
    "github.com/agiledragon/gomonkey"
    "reflect"
    "testing"
)

func SomeFunction(arg int) int {
    return arg * 2
}

type MyStruct struct{}

func (m *MyStruct) myMethod() int {
    return 10
}

func TestSomeFunction(t *testing.T) {
    // 为 SomeFunction 打桩,返回固定值 42
    patches := gomonkey.ApplyFunc(SomeFunction, func(arg int) int {
        return 42
    })
    defer patches.Reset()

    result := SomeFunction(5)
    if result != 42 {
        t.Errorf("Expected 42, got %d", result)
    }
}

func TestMyStructMethod(t *testing.T) {
    // 为 MyStruct 的 myMethod 打桩,返回固定值 42
    patches := gomonkey.ApplyMethod(reflect.TypeOf(&MyStruct{}), "myMethod", func(_ *MyStruct) int {
        return 42
    })
    defer patches.Reset()

    m := &MyStruct{}
    result := m.myMethod()
    if result != 42 {
        t.Errorf("Expected 42, got %d", result)
    }
}

通过以上示例,你可以看到如何使用 GoMonkey 为函数和方法打桩,从而在单元测试中模拟不同的行为和返回值。

posted @   guanyubo  阅读(76)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2024-01-17 设计模式 经典问题
2024-01-17 C++ 面试题(施工中...)
2024-01-17 静态库和动态库
2024-01-17 回溯 Backtrack
2024-01-17 哈希表 HashMap
2024-01-17 滑动窗口 Sliding window
2024-01-17 算法学习资料
点击右上角即可分享
微信分享提示