github.com/bytedance/mockey@v1.2.10/README_cn.md (about)

     1  # Mockey 
     2  
     3  [English](README.md) | 中文
     4  
     5  Mockey 是一款简单易用的 Golang 打桩工具库,能够快速方便地进行函数、变量的 mock,目前在字节跳动各业务的单元测试编写中应用较为广泛,其底层是通过运行时改写函数指令实现的猴子补丁(Monkey Patch)
     6  
     7  > 1. 编译时需要**禁用内联和编译优化**,否则可能会 mock 失败或者报错,详见下面的 [FAQ](#FAQ) 章节
     8  > 2. 实际编写单测的过程中,建议结合 [Convey](https://github.com/smartystreets/goconvey) 库一起使用
     9  
    10  ## 安装
    11  ```
    12  go get github.com/bytedance/mockey@latest
    13  ```
    14  
    15  ## 快速上手
    16  ```go
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	. "github.com/bytedance/mockey"
    22  	. "github.com/smartystreets/goconvey/convey"
    23  )
    24  
    25  func Foo(in string) string {
    26  	return in
    27  }
    28  
    29  type A struct{}
    30  
    31  func (a A) Foo(in string) string { return in }
    32  
    33  var Bar = 0
    34  
    35  func TestMockXXX(t *testing.T) {
    36  	PatchConvey("TestMockXXX", t, func() {
    37  		Mock(Foo).Return("c").Build()   // mock函数 
    38  		Mock(A.Foo).Return("c").Build() // mock方法 
    39  		MockValue(&Bar).To(1)           // mock变量 
    40  
    41  		So(Foo("a"), ShouldEqual, "c")        // 断言`Foo`成功mock 
    42  		So(new(A).Foo("b"), ShouldEqual, "c") // 断言`A.Foo`成功mock 
    43  		So(Bar, ShouldEqual, 1)               // 断言`Bar`成功mock 
    44  	})
    45  	// `PatchConvey`外自动释放mock
    46  	fmt.Println(Foo("a"))        // a
    47  	fmt.Println(new(A).Foo("b")) // b
    48  	fmt.Println(Bar)             // 0
    49  }
    50  ```
    51  ## 功能概览
    52  - mock 函数和方法
    53    - 基础功能
    54      - 普通/可变参数函数
    55      - 普通/可变参数方法
    56      - 嵌套结构体方法
    57      - 私有类型的导出方法(不同包下)
    58    - 高级功能
    59      - mock 后执行原函数
    60      - goroutine 条件过滤
    61      - 增量改变 mock 行为
    62      - 获取原函数执行次数
    63      - 获取 mock 函数执行次数
    64  - mock 变量
    65    - 普通变量
    66    - 函数变量
    67  ## 兼容性
    68  ### 平台支持
    69  - Mac OS(Darwin)
    70  - Linux
    71  - Windows
    72  ### 架构支持
    73  - AMD64
    74  - ARM64
    75  ### 版本支持
    76  - Go 1.13+
    77  
    78  ## 开源许可
    79  
    80  Mockey 基于[Apache License 2.0](https://github.com/bytedance/mockey/blob/main/LICENSE-APACHE) 许可证,其依赖的三方组件的开源许可见 [Licenses](https://github.com/bytedance/mockey/blob/main/licenses)
    81  
    82  ## FAQ
    83  
    84  ### 如何禁用内联和编译优化?
    85  1. 命令行:`go test -gcflags="all=-l -N" -v ./...`
    86  2. Goland:在 **运行/调试配置 > Go工具实参** 对话框中填写 `-gcflags="all=-l -N"` 
    87  
    88  ### Mock 函数后仍走入了原函数?
    89  1. 未禁用内联或者编译优化:可以尝试使用 debug 模式,如果能跑过则说明是该问题,请转到 FAQ [相关章节](#如何禁用内联和编译优化)
    90  2. 未调用`Build()`方法:mock 函数时漏写了`.Build()`,导致没有任何实际效果产生
    91  3. 目标函数不完全匹配:
    92  ```go
    93  func TestXXX(t *testing.T) {
    94  Mock((*A).Foo).Return("c").Build()
    95  fmt.Println(A{}.Foo("a")) // 走入原函数,目标函数应该是A.Foo
    96  
    97  a := A{}
    98  Mock(a.Foo).Return("c").Build()
    99  fmt.Println(a.Foo("a")) // 走入原函数,目标函数应该是A.Foo或者使用工具函数GetMethod从a中获取 
   100  }
   101  ```
   102  4. 目标函数在其他协程里执行:
   103  ```go
   104  func TestXXX(t *testing.T) {
   105     PatchConvey("TestXXX", t, func() {
   106        Mock(Foo).Return("c").Build()
   107        go Foo("a") // 执行Foo的时机不定
   108     })
   109     // 主协程走到这里时相关mock已经被PatchConvey释放,如果Foo先于此执行则mock成功,否则失败
   110     fmt.Println("over")
   111     time.Sleep(time.Second)
   112  }
   113  ```
   114  
   115  ### 报错 "function is too short to patch"?
   116  1. 未禁用内联或者编译优化:可以尝试使用 debug 模式,如果能跑过则说明是该问题,请转到 FAQ [相关章节](#如何禁用内联和编译优化)
   117  2. 函数确实太短:指目标函数小于一行,导致编译后机器码太短,一般两行及以上不会有这个问题
   118  3. 重复 mock 同一个函数:在最小单位的`PatchConvey`中重复 mock 同一个函数,如果确实有这种需求可以尝试获取`Mocker`后重新 mock
   119  4. 其他工具 mock 了该函数:例如已经使用 [monkey](https://github.com/bouk/monkey) 等工具 mock 了该函数