GO语言做单元测试,常用框架是convey+monkey
monkey的教程比较少,所以这里我也记录一下我自己的学习过程

go mod init test
gomonkey 1.0 特性列表

支持为一个函数打一个桩
支持为一个成员方法打一个桩
支持为一个全局变量打一个桩
支持为一个函数变量打一个桩
支持为一个函数打一个特定的桩序列
支持为一个成员方法打一个特定的桩序列
支持为一个函数变量打一个特定的桩序列





为一个函数打一个桩

ApplyFunc 第一个参数是函数名,第二个参数是桩函数。测试完成后,patches 对象通过 Reset 成员方法删除所有测试桩。

1.在test文件夹中新建func_test.go

package test

import (
	. "github.com/agiledragon/gomonkey"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
	"github.com/agiledragon/gomonkey/test/fake"
	"encoding/json"
)
var (
	outputExpect = "xxx-vethName100-yyy"
)
//函数
//ApplyFunc 第一个参数是函数名,第二个参数是桩函数。测试完成后,patches 对象通过 Reset 成员方法删除所有测试桩。
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(_ []byte, v interface{
   
   }) error {
   
   
				p := v.(*map[int]int)
				*p = make(map[int]int)
				(*p)[1] = 2
				(*p)[2] = 4
				return nil
			})
			defer patches.Reset()
			var m map[int]int
			err := json.Unmarshal(nil, &m)
			So(err, ShouldEqual, nil)
			So(m[1], ShouldEqual, 2)
			So(m[2], ShouldEqual, 4)
		})
	})
}
go mod tidy
go test -v func_test.go
支持为一个成员方法打一个桩

ApplyMethod 第一个参数是目标类的指针变量的反射类型,第二个参数是字符串形式的方法名,第三个参数是桩函数。

1.在test文件夹中新建method_test.go

package test

import (
	. "github.com/agiledragon/gomonkey"
	"github.com/agiledragon/gomonkey/test/fake"
	. "github.com/smartystreets/goconvey/convey"
	"reflect"
	"testing"
)
//成员方法
//ApplyMethod 第一个参数是目标类的指针变量的反射类型,第二个参数是字符串形式的方法名,第三个参数是桩函数。
//测试完成后,patches 对象通过 Reset 成员方法删除所有测试桩。
func TestApplyMethod(t *testing.T) {
   
   
	slice := fake.NewSlice()
	var s *fake.Slice
	Convey("TestApplyMethod", t, func() {
   
   
		Convey("for succ\n", 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\n", 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\n", 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\n", 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)
		})
	})
}
支持为一个全局变量打一个桩

未完待续~