go monkey

定义

golang用来做 monkey patching 的测试库。

monkey patch :在运行时,动态修改一些变量/函数/方法/模块 的行为的能力。

对于有些三方的库,我们没有权限去调整代码逻辑,而这又会对我们测试带来影响,所以,我们通过【运行时替换】的方法来改掉这些实体的行为。

导包

import "github.com/agiledragon/gomonkey/v2"

使用注意事项

  1. gomonkey库只支持Arch架构,不能够在x86/amd上运行使用。
  2. 测试时需要关闭内联优化

go test -gcflags=all=-l

因为内联消除了调用目标函数时的跳转操作,使得go monkey填充在目标函数入口处的指令无法执行,因而也无法实现函数体的运行时替换,使go monkey失效。

使用示例

函数打桩

func ApplyFunc(target, double interface{}) *Patches
参数:target 目标函数,double替代函数

1.将clean函数用匿名函数代替

func clean() bool {
	println("do clean()")
	return true
}
func TestMonkey(t *testing.T) {
	println("monkey test")
	
	patchers := gomonkey.ApplyFunc(clean, func() bool {
		return false
	})
	defer patchers.Reset() //重置桩

	if clean() == true {
		t.Fatal("true")
	} else {
		t.Fatal("false") //最后运行了这一行,clean函数被替代
	}
  1. time.Now永远返回固定时间
func TestMonkey(t *testing.T) {
	println("monkey test")
	now := time.Now()
	gomonkey.ApplyFunc(time.Now, func() time.Time {
		return now
	})
	defer patchers.Reset()
	
	fmt.Println(time.Now())
	time.Sleep(time.Second * 3)
	fmt.Println(time.Now()) //这里与上面的结果相同

}

方法打桩

func ApplyMethod(target reflect.Type, methodName string, double interface{}) *Patches
参数:
target:目标类型,根据reflect.TypeOf()获得。
methodName:方法名
double:替代函数,替代函数的第一个参数需要为对象类型或对象的指针

type A int

func (a A) Print1(n int) {
	println(n)
}
func TestMonkey(t *testing.T) {
	var g_A A
	patches := gomonkey.ApplyMethod(reflect.TypeOf(g_A), "Print1", func(a A, n int) {
		println("hello world")
	})
	defer patches.Reset()

	g_A.Print1(3) //如果没有被替代会打印3,实际上打印了helloworld
	t.Fatal("end") //不出错的话,println不会显示

}

全局变量打桩

var c = 3

func TestMonkey(t *testing.T) {
	patches :=gomonkey.ApplyGlobalVar(&c, 4)
	defer patches.Reset()
	
	println(c)//输出4
	t.Fatal("end")
}

参考:https://juejin.cn/post/7133520098123317256

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Go语言中,你可以使用`gomonkey`库来进行接口的模拟(mock)。`gomonkey`是一个用于在测试中进行mock的库,它可以帮助你模拟接口的实现,并在测试过程中替换原始的接口。 下面是一个简单的示例,演示了如何使用`gomonkey`库来模拟接口: ```go package main import ( "fmt" "github.com/agiledragon/gomonkey" ) // 定义一个接口 type MyInterface interface { DoSomething() string } // 实现接口的结构体 type MyStruct struct{} func (m *MyStruct) DoSomething() string { return "Real implementation" } func main() { // 创建一个gomonkey实例 patch := gomonkey.NewPatches() // 创建一个模拟对象 mock := &MyStruct{} // 注册模拟对象到gomonkey实例中 patch.ApplyMethod(reflect.TypeOf(mock), "DoSomething", func(_ *MyStruct) string { return "Mocked implementation" }) // 在函数结束时恢复被修改的函数 defer patch.Reset() // 调用被模拟的接口方法 fmt.Println(mock.DoSomething()) // 输出: Mocked implementation } ``` 在上述代码中,我们首先定义了一个接口`MyInterface`和一个实现了该接口的结构体`MyStruct`。然后,我们使用`gomonkey`库创建了一个`Patches`对象,并通过`ApplyMethod`方法将模拟对象注册到该`Patches`对象中。 在`ApplyMethod`函数中,我们指定了要替换的方法,以及一个匿名函数作为替代实现。在这个示例中,我们将`DoSomething`方法的实现替换为返回固定字符串"Mocked implementation"。最后,我们通过调用模拟对象的方法来验证替代实现是否生效。 在函数结束时,我们使用`Reset`方法来恢复被修改的函数,以确保不会影响其他部分的测试。 需要注意的是,`gomonkey`库可以用于在测试中模拟函数、方法和全局变量,不仅限于接口的模拟。具体使用方式可以根据实际需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值