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
是替换后的函数。
例如,将 MyStruct
的 myMethod
替换为返回 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()
注意事项
- 关闭内联优化:GoMonkey 不支持内联函数,在测试时需要通过命令行参数
-gcflags=-l
(Go 1.10 以下)或-gcflags=all=-l
(Go 1.10 及以上)关闭 Go 语言的内联优化 - 线程安全: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 为函数和方法打桩,从而在单元测试中模拟不同的行为和返回值。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用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 算法学习资料