
omonkey.ApplyMethod()、gomonkey.ApplyMethodFunc()区别匹配方式不同ApplyMethod是名称匹配ApplyMethodFunc是函数本体匹配传参核心不同ApplyMethod必须传reflect.Type方法名字符串ApplyMethodFunc直接传原方法函数不需要反射底层逻辑不同ApplyMethod是「反射查找方法」ApplyMethodFunc是「直接绑定方法函数」后者性能更高gomonkey.ApplyMethod() 参数示例// 第一个参数要打桩的方法所属的类型通过 reflect.TypeOf(实例) 获取区分值接收者 / 指针接收者// 第二个参数要打桩的方法名字符串格式、大小写敏感必须和原方法名完全一致// 第三个参数打桩方法入参和出参要保持和被打桩方法保持一致但需注意需要额外传入结构体类型且必须是第一个参数func ApplyMethod(target interface{}, methodName string, double interface{}) *Patches {return create().ApplyMethod(target, methodName, double)}gomonkey.ApplyMethodFunc() 参数示例// 第一个参数要打桩的方法所属的类型通过 reflect.TypeOf(实例) 获取区分值接收者 / 指针接收者// 第二个参数要打桩的方法名字符串格式、大小写敏感必须和原方法名完全一致// 第三个参数打桩方法入参和出参要保持和被打桩方法保持一致不需要额外参数func ApplyMethodFunc(target interface{}, methodName string, doubleFunc interface{}) *Patches {return create().ApplyMethodFunc(target, methodName, doubleFunc)}注意可以不用写reflect.TypeOf(实例)如果了解方法所属类型可以直接写方法类型而不用reflect.TypeOf()在获取一次gomonkey.ApplyMethod()method_demo.gotype MethodDemo struct {}func (m MethodDemo) MethodDemo(ret string) {fmt.Println(MethodDemo:, ret)}func (m *MethodDemo) MethodPointerDemo(ret string) {fmt.Println(MethodPointerDemo:, ret)}method_demo_test.go// 基于 gomonkey.ApplyMethod() 的单元测试【指针接收者专用写法】 func TestMethodPointerDemo(t *testing.T) {// 1. 初始化【指针类型】的结构体实例 (必须是指针和方法接收者对应)md : MethodDemo{}patches : gomonkey.NewPatches()// 铁律延迟撤销打桩防止污染其他测试用例必写defer patches.Reset()// 2. 核心gomonkey.ApplyMethod() 打桩【指针接收者方法】// 第一个参数reflect.TypeOf(md) 传入指针实例获取 *MethodDemo 的反射类型 【必须传指针实例】// 第二个参数方法名字符串严格大小写一致// 第三个参数mock桩函数入参规则严格匹配patches.ApplyMethod(// 可以直接写 MethodDemo{}reflect.TypeOf(md),MethodPointerDemo,// mock桩函数规则// ① 第一个入参必须是【指针接收者】 *MethodDemo 和原方法一致// ② 第二个入参原方法的入参 ret string和原方法一致// ③ 原方法无返回值桩函数也必须无返回值func(m *MethodDemo, ret string) {// 自定义mock逻辑替代原方法的 fmt.Println 逻辑t.Log(✅ 指针方法打桩生效入参ret , ret)},)// 3. 调用被打桩的指针方法验证mock是否生效md.MethodPointerDemo(hello gomonkey 指针接收者)}命令行执行命令go test -run ^TestMethodPointerDemo$ -gcflagsall-l结果PS D:\wyl\workspace\go\tracer\logic\method_demo go test -run ^TestMethodPointerDemo$ -coverMethodPointerDemo: hello gomonkey 指针接收者PASScoverage: 25.0% of statementsok tracer/logic/method_demo 0.277sPS D:\wyl\workspace\go\tracer\logic\method_demo go test -run ^TestMethodPointerDemo$ -gcflagsall-lPASSok tracer/logic/method_demo 0.266sgomonkey.ApplyMethodFunc()method_func_demo.gotype MethodFuncDemo struct {}func (m MethodFuncDemo) MethodFuncDemo(ret string) {fmt.Println(MethodFuncDemo:, ret)}func (m *MethodFuncDemo) MethodFuncPrinterDemo(ret string) {fmt.Println(MethodFuncPrinterDemo:, ret)}method_func_demo_test.go// 指针接收者 对应的 ApplyMethodFunc 单元测试 func TestMethodFuncPointerDemo(t *testing.T) {// 1. 初始化指针类型的结构体实例mfd : MethodFuncDemo{}patches : gomonkey.NewPatches()// 铁律延迟撤销打桩防止污染其他测试用例必写defer patches.Reset()// 2. 核心gomonkey.ApplyMethodFunc 打桩【指针接收者方法】// ✅ 第一个参数直接传【指针接收者的方法本体】 语法固定(*结构体名).方法名patches.ApplyMethodFunc(// 重点指针接收者的方法本体写法mfd,MethodFuncPrinterDemo,func(m *MethodFuncDemo, ret string) {// 桩函数第一个入参必须是 指针类型 *MethodFuncDemot.Log(✅ MethodFuncPrinterDemo 指针接收者打桩生效入参ret , ret)},)// 3. 调用指针方法mfd.MethodFuncPrinterDemo(hello gomonkey 指针接收者)}命令行执行命令go test -run ^TestMethodFuncPointerDemo$ -gcflagsall-l结果PS D:\wyl\workspace\go\tracer\logic\method_demo go test -run ^TestMethodFuncPointerDemo$ -coverMethodFuncPrinterDemo: hello gomonkey 指针接收者PASScoverage: 25.0% of statementsok tracer/logic/method_demo 0.275sPS D:\wyl\workspace\go\tracer\logic\method_demo go test -run ^TestMethodFuncPointerDemo$ -gcflagsall-lPASSok tracer/logic/method_demo 0.227s4多次调用顺序返回不同结果gomonkey.ApplyMethodSeq()高频实用方法处理「结构体方法被多次调用需要返回不同结果」的核心方法完美解决方法第 1 次调用返回 A、第 2 次返回 B、第 N 次返回默认值 / 报错 这类高频业务场景。这个也和上面2和3一样支持两种写法函数和结构体方法写法类似这里就只写一个示例了参数示例