🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] > https://github.com/agiledragon/gomonkey ## 概述 - 可动态的改变被调用函数的返回值 - 但是执行 `go test` 需要添加 `-gcflags=all=-l`,关闭 Go 语言的内联优化才能生效 - mock 不会再新的 协程中生效 ## IDEA 配置 模板,默认添加 gcflags ![](https://img.kancloud.cn/8b/b7/8bb79943c8526640d9a35d9e81104b39_1044x676.png) 配置后,默认的单元测试都自动添加了 gcflag ## 示例 ### 函数打桩 <details> <summary>函数打桩</summary> ``` func networkCompute(a, b int) (int, error) { // do something in remote computer c := a + b return c, nil } func Compute(a, b int) (int, error) { sum, err := networkCompute(a, b) return sum, err } func TestCompute(t *testing.T) { // 对中间函数进行打桩 patches := gomonkey.ApplyFunc(networkCompute, func(a, b int) (int, error) { return 2, nil }) defer patches.Reset() sum, err := Compute(1, 1) if sum != 2 || err != nil { t.Errorf("expected %v, got %v", 2, sum) } } ``` </details> ``` go test -gcflag=all=-1 ``` ### mock 方法 <details> <summary>mock 方法</summary> ``` type Computer struct { } func (t *Computer) NetworkCompute(a, b int) (int, error) { // do something in remote computer c := a + b return c, nil } func (t *Computer) Compute(a, b int) (int, error) { sum, err := t.NetworkCompute(a, b) return sum, err } func TestCompute(t *testing.T) { var c *Computer patches := gomonkey.ApplyMethod(reflect.TypeOf(c), "NetworkCompute", func(_ *Computer, a, b int) (int, error) { return 2, nil }) defer patches.Reset() cp := &Computer{} sum, err := cp.Compute(1, 1) if sum != 2 || err != nil { t.Errorf("expected %v, got %v", 2, sum) } } ``` </details> ### mock json.Marshal <details> <summary>mock json.Marsha</summary> ``` type Host struct { IP string Name string } func Convert2Json(h *Host) (string, error) { b, err := json.Marshal(h) return string(b), err } func TestConvert2Json(t *testing.T) { patches := gomonkey.ApplyFunc(json.Marshal, func(v interface{}) ([]byte, error) { return []byte(`{"IP":"192.168.23.92","Name":"Sky"}`), nil }) defer patches.Reset() h := Host{Name: "Sky", IP: "192.168.23.92"} s, err := Convert2Json(&h) expectedString := `{"IP":"192.168.23.92","Name":"Sky"}` if s != expectedString || err != nil { t.Errorf("expected %v, got %v", expectedString, s) } } ``` </details> ### mock 一个全局变量 <details> <summary></summary> ``` import ( "testing" "github.com/agiledragon/gomonkey" ) var num = 10 func TestGlobalVar(t *testing.T) { patches := gomonkey.ApplyGlobalVar(&num, 12) defer patches.Reset() if num != 12 { t.Errorf("expected %v, got %v", 12, num) } } ``` </details> ### mock 多次调用,返回不同结果 <details> <summary></summary> ``` import ( "testing" "github.com/agiledragon/gomonkey" ) func compute(a, b int) (int, error) { return a + b, nil } func TestFunc(t *testing.T) { info1 := 2 info2 := 3 info3 := 4 outputs := []gomonkey.OutputCell{ {Values: gomonkey.Params{info1, nil}}, // 模拟函数的第1次输出 {Values: gomonkey.Params{info2, nil}}, // 模拟函数的第2次输出 {Values: gomonkey.Params{info3, nil}}, // 模拟函数的第3次输出 } patches := gomonkey.ApplyFuncSeq(compute, outputs) defer patches.Reset() output, err := compute(1, 1) if output != 2 || err != nil { t.Errorf("expected %v, got %v", 2, output) } output, err = compute(1, 2) if output != 3 || err != nil { t.Errorf("expected %v, got %v", 2, output) } output, err = compute(1, 3) if output != 4 || err != nil { t.Errorf("expected %v, got %v", 2, output) } } ``` </details>