西安保洁公司网站建设,互联网保险的风险,dedecms网站主页空白,背景wordpress文章目录 gomonkey调研文档和学习gomonkey概述examples1 为函数打桩2 函数打序列桩3、函数变量打桩5、全局变量打桩6、成员方法打桩7、成员方法打序列桩8、接口打桩 总结 gomonkey调研文档和学习
gomonkey概述
学习地址 gomonkey 是 golang 的一款打桩框架#xff0c;目标是… 文章目录 gomonkey调研文档和学习gomonkey概述examples1 为函数打桩2 函数打序列桩3、函数变量打桩5、全局变量打桩6、成员方法打桩7、成员方法打序列桩8、接口打桩 总结 gomonkey调研文档和学习
gomonkey概述
学习地址 gomonkey 是 golang 的一款打桩框架目标是让用户在单元测试中低成本的完成打桩从而将精力聚焦于业务功能的开发。 特性列表
支持为一个函数打一个桩支持为一个成员方法打一个桩支持为一个接口打一个桩支持为一个全局变量打一个桩支持为一个函数变量打一个桩支持为一个函数打一个特定的桩序列支持为一个成员方法打一个特定的桩序列支持为一个函数变量打一个特定的桩序列支持为一个接口打一个特定的桩序列
examples
例子中所有的代码都在这https://github.com/fishingfly/gomonkey_examples
1 为函数打桩
ApplyFunc 第一个参数是函数名第二个参数是桩函数。测试完成后patches 对象通过 Reset 成员方法删除所有测试桩。
package testimport (./fakeencoding/json. github.com/agiledragon/gomonkey. github.com/smartystreets/goconvey/conveytesting
)var (outputExpect xxx-vethName100-yyy
)func TestApplyFunc(t *testing.T) {Convey(TestApplyFunc, t, func() {Convey(one func for succ, func() {patches : ApplyFunc(fake.Exec, func(_ string, _ ...string) (string, error) {return outputExpect, nil})defer patches.Reset()output, err : fake.Exec(, )So(err, ShouldEqual, nil)So(output, ShouldEqual, outputExpect)})Convey(one func for fail, func() {patches : ApplyFunc(fake.Exec, func(_ string, _ ...string) (string, error) {return , fake.ErrActual})defer patches.Reset()output, err : fake.Exec(, )So(err, ShouldEqual, fake.ErrActual)So(output, ShouldEqual, )})Convey(two funcs, func() {patches : ApplyFunc(fake.Exec, func(_ string, _ ...string) (string, error) {return outputExpect, nil})defer patches.Reset()patches.ApplyFunc(fake.Belong, func(_ string, _ []string) bool {return true})output, err : fake.Exec(, )So(err, ShouldEqual, nil)So(output, ShouldEqual, outputExpect)flag : fake.Belong(, nil)So(flag, ShouldBeTrue)})Convey(input and output param, func() {patches : ApplyFunc(json.Unmarshal, func(data []byte, v interface{}) error {if data nil {panic(input param is nil!)}p : v.(*map[int]int)*p make(map[int]int)(*p)[1] 2(*p)[2] 4return nil})defer patches.Reset()var m map[int]interr : json.Unmarshal([]byte(123), m)So(err, ShouldEqual, nil)So(m[1], ShouldEqual, 2)So(m[2], ShouldEqual, 4)})})
}这边是对fake.exec函数打桩模拟exec函数的输出。,fake.exec函数在fake目录下可以来下我的代码库看下。 上面这种模拟函数输出有啥应用从我实际使用的角度出发我们看下面例子 mytest.go
package mytestfunc AddOne(t int32) int32 {return t1
}func MinusOne(t int32) int32 {return t-1
}func MultiAddOne(t int32) int32 {t MinusOne(t)t AddOne(t)t AddOne(t)return t
}测试类mytest_test.go
package mytestimport (. github.com/agiledragon/gomonkey. github.com/smartystreets/goconvey/conveytesting
)func TestMultiAddOne(t *testing.T) {Convey(TestApplyFunc, t, func() {Convey(input and output param, func() {patches : ApplyFunc(AddOne, func(t1 int32) int32 {return 0})//对函数AddOne打桩defer patches.Reset()patches.ApplyFunc(MinusOne, func(t1 int32) int32 {return -1})//对函数MinusOne打桩result : MultiAddOne(10) //看好了我调用的是MultiAddOne函数而MultiAddOne函数内部调用了AddOne和MinusOne。So(result, ShouldEqual, 0)})})
}
我模拟了AddOne和MinusOne函数的输出以达到MultiAddOne函数的效果。
2 函数打序列桩
ApplyFuncSeq第一个参数是函数名第二个参数是特定的桩序列参数。测试完成后patches 对象通过 Reset 成员方法删除所有测试桩。
package testimport (. github.com/agiledragon/gomonkeygithub.com/agiledragon/gomonkey/test/fake. github.com/smartystreets/goconvey/conveytesting
)func TestApplyFuncSeq(t *testing.T) {Convey(TestApplyFuncSeq, t, func() {Convey(default times is 1, func() {info1 : hello cppinfo2 : hello golanginfo3 : hello gomonkeyoutputs : []OutputCell{{Values: Params{info1, nil}},// 模拟函数的第1次输出{Values: Params{info2, nil}},// 模拟函数的第2次输出{Values: Params{info3, nil}},// 模拟函数的第3次输出}patches : ApplyFuncSeq(fake.ReadLeaf, outputs)defer patches.Reset()output, err : fake.ReadLeaf()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)output, err fake.ReadLeaf()So(err, ShouldEqual, nil)So(output, ShouldEqual, info2)output, err fake.ReadLeaf()So(err, ShouldEqual, nil)So(output, ShouldEqual, info3)})Convey(retry succ util the third times, func() {info1 : hello cppoutputs : []OutputCell{{Values: Params{, fake.ErrActual}, Times: 2},// 模拟函数的第1次输出{Values: Params{info1, nil}},// 模拟函数的第2次输出}patches : ApplyFuncSeq(fake.ReadLeaf, outputs)defer patches.Reset()output, err : fake.ReadLeaf()So(err, ShouldEqual, fake.ErrActual)output, err fake.ReadLeaf()So(err, ShouldEqual, fake.ErrActual)output, err fake.ReadLeaf()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)})Convey(batch operations failed on the third time, func() {info1 : hello gomonkeyoutputs : []OutputCell{{Values: Params{info1, nil}, Times: 2},{Values: Params{, fake.ErrActual}},}patches : ApplyFuncSeq(fake.ReadLeaf, outputs)defer patches.Reset()output, err : fake.ReadLeaf()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)output, err fake.ReadLeaf()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)output, err fake.ReadLeaf()So(err, ShouldEqual, fake.ErrActual)})})
}3、函数变量打桩
ApplyFuncVar 第一个参数是函数变量的地址第二个参数是桩函数。测试完成后patches 对象通过 Reset 成员方法删除所有测试桩。
package testimport (. github.com/agiledragon/gomonkeygithub.com/agiledragon/gomonkey/test/fake. github.com/smartystreets/goconvey/conveytesting
)func TestApplyFuncVar(t *testing.T) {Convey(TestApplyFuncVar, t, func() {Convey(for succ, func() {str : hellopatches : ApplyFuncVar(fake.Marshal, func (_ interface{}) ([]byte, error) {return []byte(str), nil})// fake.Marshal是函数变量defer patches.Reset()bytes, err : fake.Marshal(nil)So(err, ShouldEqual, nil)So(string(bytes), ShouldEqual, str)})Convey(for fail, func() {patches : ApplyFuncVar(fake.Marshal, func (_ interface{}) ([]byte, error) {return nil, fake.ErrActual})defer patches.Reset()_, err : fake.Marshal(nil)So(err, ShouldEqual, fake.ErrActual)})})
}4、函数变量打序列桩 ApplyFuncVarSeq 第一个参数是函数变量地址第二个参数是特定的桩序列参数。测试完成后patches 对象通过 Reset 成员方法删除所有测试桩。
package testimport (. github.com/agiledragon/gomonkeygithub.com/agiledragon/gomonkey/test/fake. github.com/smartystreets/goconvey/conveytesting
)func TestApplyFuncVarSeq(t *testing.T) {Convey(TestApplyFuncVarSeq, t, func() {Convey(default times is 1, func() {info1 : hello cppinfo2 : hello golanginfo3 : hello gomonkeyoutputs : []OutputCell{{Values: Params{[]byte(info1), nil}},{Values: Params{[]byte(info2), nil}},{Values: Params{[]byte(info3), nil}},}patches : ApplyFuncVarSeq(fake.Marshal, outputs)defer patches.Reset()bytes, err : fake.Marshal()So(err, ShouldEqual, nil)So(string(bytes), ShouldEqual, info1)bytes, err fake.Marshal()So(err, ShouldEqual, nil)So(string(bytes), ShouldEqual, info2)bytes, err fake.Marshal()So(err, ShouldEqual, nil)So(string(bytes), ShouldEqual, info3)})Convey(retry succ util the third times, func() {info1 : hello cppoutputs : []OutputCell{{Values: Params{[]byte(), fake.ErrActual}, Times: 2},{Values: Params{[]byte(info1), nil}},}patches : ApplyFuncVarSeq(fake.Marshal, outputs)defer patches.Reset()bytes, err : fake.Marshal()So(err, ShouldEqual, fake.ErrActual)bytes, err fake.Marshal()So(err, ShouldEqual, fake.ErrActual)bytes, err fake.Marshal()So(err, ShouldEqual, nil)So(string(bytes), ShouldEqual, info1)})Convey(batch operations failed on the third time, func() {info1 : hello gomonkeyoutputs : []OutputCell{{Values: Params{[]byte(info1), nil}, Times: 2},{Values: Params{[]byte(), fake.ErrActual}},}patches : ApplyFuncVarSeq(fake.Marshal, outputs)defer patches.Reset()bytes, err : fake.Marshal()So(err, ShouldEqual, nil)So(string(bytes), ShouldEqual, info1)bytes, err fake.Marshal()So(err, ShouldEqual, nil)So(string(bytes), ShouldEqual, info1)bytes, err fake.Marshal()So(err, ShouldEqual, fake.ErrActual)})})
}5、全局变量打桩
ApplyGlobalVar 第一个参数是全局变量的地址第二个参数是全局变量的桩。测试完成后patches 对象通过 Reset 成员方法删除所有测试桩。
package testimport (. github.com/agiledragon/gomonkey. github.com/smartystreets/goconvey/conveytesting
)var num 10 //全局变量func TestApplyGlobalVar(t *testing.T) {Convey(TestApplyGlobalVar, t, func() {Convey(change, func() {patches : ApplyGlobalVar(num, 150)defer patches.Reset()So(num, ShouldEqual, 150)})Convey(recover, func() {So(num, ShouldEqual, 10)})})
}6、成员方法打桩
ApplyMethod 第一个参数是目标类的指针变量的反射类型第二个参数是字符串形式的方法名第三个参数是桩函数。测试完成后patches 对象通过 Reset 成员方法删除所有测试桩。
package testimport (. github.com/agiledragon/gomonkey. github.com/smartystreets/goconvey/conveygomonkeytest/fakereflecttesting
)func TestApplyMethod(t *testing.T) {slice : fake.NewSlice()var s *fake.SliceConvey(TestApplyMethod, t, func() {Convey(for succ, func() {err : slice.Add(1)So(err, ShouldEqual, nil)patches : ApplyMethod(reflect.TypeOf(s), Add, func(_ *fake.Slice, _ int) error {return nil})defer patches.Reset()err slice.Add(1)So(err, ShouldEqual, nil)err slice.Remove(1)So(err, ShouldEqual, nil)So(len(slice), ShouldEqual, 0)})Convey(for already exist, func() {err : slice.Add(2)So(err, ShouldEqual, nil)patches : ApplyMethod(reflect.TypeOf(s), Add, func(_ *fake.Slice, _ int) error {return fake.ErrElemExsit})defer patches.Reset()err slice.Add(1)So(err, ShouldEqual, fake.ErrElemExsit)err slice.Remove(2)So(err, ShouldEqual, nil)So(len(slice), ShouldEqual, 0)})Convey(two methods, func() {err : slice.Add(3)So(err, ShouldEqual, nil)defer slice.Remove(3)patches : ApplyMethod(reflect.TypeOf(s), Add, func(_ *fake.Slice, _ int) error {return fake.ErrElemExsit})defer patches.Reset()patches.ApplyMethod(reflect.TypeOf(s), Remove, func(_ *fake.Slice, _ int) error {return fake.ErrElemNotExsit})err slice.Add(2)So(err, ShouldEqual, fake.ErrElemExsit)err slice.Remove(1)So(err, ShouldEqual, fake.ErrElemNotExsit)So(len(slice), ShouldEqual, 1)So(slice[0], ShouldEqual, 3)})Convey(one func and one method, func() {err : slice.Add(4)So(err, ShouldEqual, nil)defer slice.Remove(4)patches : ApplyFunc(fake.Exec, func(_ string, _ ...string) (string, error) {return outputExpect, nil})defer patches.Reset()patches.ApplyMethod(reflect.TypeOf(s), Remove, func(_ *fake.Slice, _ int) error {return fake.ErrElemNotExsit})output, err : fake.Exec(, )So(err, ShouldEqual, nil)So(output, ShouldEqual, outputExpect)err slice.Remove(1)So(err, ShouldEqual, fake.ErrElemNotExsit)So(len(slice), ShouldEqual, 1)So(slice[0], ShouldEqual, 4)})})
}7、成员方法打序列桩
ApplyMethodSeq 第一个参数是目标类的指针变量的反射类型第二个参数是字符串形式的方法名第三参数是特定的桩序列参数。测试完成后patches 对象通过 Reset 成员方法删除所有测试桩。
package testimport (. github.com/agiledragon/gomonkeygithub.com/agiledragon/gomonkey/test/fake. github.com/smartystreets/goconvey/conveyreflecttesting
)func TestApplyMethodSeq(t *testing.T) {e : fake.Etcd{}Convey(TestApplyMethodSeq, t, func() {Convey(default times is 1, func() {info1 : hello cppinfo2 : hello golanginfo3 : hello gomonkeyoutputs : []OutputCell{{Values: Params{info1, nil}},{Values: Params{info2, nil}},{Values: Params{info3, nil}},}patches : ApplyMethodSeq(reflect.TypeOf(e), Retrieve, outputs)defer patches.Reset()output, err : e.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)output, err e.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info2)output, err e.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info3)})Convey(retry succ util the third times, func() {info1 : hello cppoutputs : []OutputCell{{Values: Params{, fake.ErrActual}, Times: 2},{Values: Params{info1, nil}},}patches : ApplyMethodSeq(reflect.TypeOf(e), Retrieve, outputs)defer patches.Reset()output, err : e.Retrieve()So(err, ShouldEqual, fake.ErrActual)output, err e.Retrieve()So(err, ShouldEqual, fake.ErrActual)output, err e.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)})Convey(batch operations failed on the third time, func() {info1 : hello gomonkeyoutputs : []OutputCell{{Values: Params{info1, nil}, Times: 2},{Values: Params{, fake.ErrActual}},}patches : ApplyMethodSeq(reflect.TypeOf(e), Retrieve, outputs)defer patches.Reset()output, err : e.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)output, err e.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)output, err e.Retrieve()So(err, ShouldEqual, fake.ErrActual)})})
}8、接口打桩
package testimport (. github.com/agiledragon/gomonkeygithub.com/agiledragon/gomonkey/test/fake. github.com/smartystreets/goconvey/conveyreflecttesting
)func TestApplyInterfaceReused(t *testing.T) {e : fake.Etcd{}Convey(TestApplyInterfaceReused, t, func() {patches : ApplyFunc(fake.NewDb, func(_ string) fake.Db {return e})defer patches.Reset()db : fake.NewDb(mysql)Convey(TestApplyInterface, func() {info : hello interfacepatches.ApplyMethod(reflect.TypeOf(e), Retrieve,func(_ *fake.Etcd, _ string) (string, error) {return info, nil})output, err : db.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info)})Convey(TestApplyInterfaceSeq, func() {info1 : hello cppinfo2 : hello golanginfo3 : hello gomonkeyoutputs : []OutputCell{{Values: Params{info1, nil}},{Values: Params{info2, nil}},{Values: Params{info3, nil}},}patches.ApplyMethodSeq(reflect.TypeOf(e), Retrieve, outputs)output, err : db.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info1)output, err db.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info2)output, err db.Retrieve()So(err, ShouldEqual, nil)So(output, ShouldEqual, info3)})})
}总结
在我看来gomonkey是弥补了goconvey的不足两者一起使用可以满足基本需要。goconvey负责断言gomonkey负责为变量和函数打桩构造各种测试条件。