美文网首页
go 单元测试(二)mock

go 单元测试(二)mock

作者: wayyyy | 来源:发表于2022-08-20 03:07 被阅读0次

当待测试的函数/对象的依赖关系很复杂,并且有些依赖不能直接创建,例如数据库连接、文件I/O等。这种场景就非常适合使用 mock/stub 测试。简单来说,就是用 mock 对象模拟依赖项的行为。

gomock

gomock 是官方提供的mock框架,同时还提供了mockgen工具用来辅助申城测试代码:
首先使用如下命令安装:

go get -u github.com/golang/mock/gomock
go get -u github.com/golang/mock/mockgen

然后再使用如下命令生成,

# mockgen -source=[源文件] -destination=[生成后的mock文件] -package=[包名]

会将源文件的接口生成mock对象。


gomonkey 库

试用了官方的,发现要先生成文件等很麻烦,搜索得到可以使用 gomonkey 这个库来mock对象。

gomonkey 提供了如下 mock 方法:

  • ApplyGlobalVar(target, double interface{}):使用 reflect 包,将 target 的值修改为 double
  • ApplyFuncVar(target, double interface{}):检查 target 是否为指针类型,与 double 函数声明是否相同,最后调用 ApplyGlobalVar
  • ApplyFunc(target, double interface{}):修改 target 的机器指令,跳转到 double 执行
  • ApplyMethod(target reflect.Type, methodName string, double interface{}):修改 method 的机器指令,跳转到 double 执行
  • ApplyFuncSeq(target interface{}, outputs []OutputCell):修改 target 的机器指令,跳转到 gomonkey 生成的一个函数执行,每次调用会顺序从 outputs 取出一个值返回
  • ApplyMethodSeq(target reflect.Type, methodName string, outputs []OutputCell):修改 target 的机器指令,跳转到 gomonkey 生成的一个方法执行,每次调用会顺序从 outputs 取出一个值返回
  • ApplyFuncVarSeq(target interface{}, outputs []OutputCell):gomonkey 生成一个函数顺序返回 outputs 中的值,调用 ApplyGlobalVar

但是有2点需要注意:

  • monkey不支持内联函数,在测试的时候需要通过命令行参数-gcflags=all=-l关闭Go语言的内联优化。
  • monkey不是线程安全的,所以不要把它用到并发的单元测试中。

gomonkey 有多个版本,我们可以使用最新的v2版本

github.com/agiledragon/gomonkey/v2
mock全局变量
var num = 10

func TestApplyGlobalVar(t *testing.T) {
    patches := gomonkey.ApplyGlobalVar(&num, 150)
    defer patches.Reset()

    assert.Equal(t, num, 150)
}
mock 函数
import (
    "github.com/agiledragon/gomonkey/v2"
    "github.com/stretchr/testify/assert"
    "testing"
)

func networkCompute(a, b int) (int, error) {
    // 假设这里依赖于其他远程服务
    c := a + b
    return c, nil
}

func Compute(a, b int) (int, error) {
    sum, err := networkCompute(a, b)
    return sum, err
}

func TestFunc(t *testing.T) {
    // mock networkCompute(),返回了计算结果2
    patches := gomonkey.ApplyFunc(networkCompute, func(a, b int) (int, error) {
        return 2, nil
    })
    // v2 还可以直接使用:
    //patches := gomonkey.ApplyFuncReturn(networkCompute, 2, nil)

    defer patches.Reset()

    sum, err := Compute(1, 2)
    assert.Equal(t, err, nil)
    assert.Equal(t, sum, 2)
}

这里有时候会打桩失败,原因是因为函数内联导致的。

mock 方法
type Task struct {
}

func (t *Task) Sub(a, b int) int {
    return a - b
}

func (t *Task) add(a, b int) int {
    return a + b
}

方法:

func TestTask_Run(t *testing.T) {
    task := &Task{}
    patches := gomonkey.ApplyMethod(task, "Sub", func(a, b int) int {
        return a + b
    })
    //patches := gomonkey.ApplyMethodReturn(task, "Sub",4)
    defer patches.Reset()

    result := task.Sub(3, 2)
    assert.Equal(t, result, 5)
}

私有方法:

func TestTask_add(t *testing.T) {
    task := &Task{}
    patches := gomonkey.ApplyPrivateMethod(task, "add", func(_ *Task, a, b int) int {
        return a * b
    })
    defer patches.Reset()

    result := task.add(3, 2)
    assert.Equal(t, result, 6)
}

参考资料
1、https://www.jianshu.com/p/25d49af216b7

相关文章

  • go 单元测试(二)mock

    当待测试的函数/对象的依赖关系很复杂,并且有些依赖不能直接创建,例如数据库连接、文件I/O等。这种场景就非常适合使...

  • python mock server实现:flask

    一、什么是mock mock,即模拟。模拟一个对象,模拟接口返回。 二、什么场景要用mock 1、单元测试: 由于...

  • Go单元测试(二):stub和mock

    一、前言介绍: 对于我们平时开发的业务代码,单个函数往往不是独立的,它需要依赖于其他模块、第三方库、数据库、消息交...

  • Robolectric框架的使用

    可以参考地址: 1.Android单元测试(一):JUnit框架的使用 2.Android单元测试(二):Mock...

  • spring-cloud feginClient unit te

    最近单元测试时碰到需要mock feginClient的接口 因为项目中存在fegin的hystrix,在mock...

  • Jmokit

    # Junit+Jmokit单元测试 标签(空格分隔):java单元测试 --- > 原理:mock测试就是在测试...

  • php单元测试进阶(13)- 核心技术 - mock对象 - 同

    php单元测试进阶(13)- 核心技术 - mock对象 - 同时使用mock和stub 本系列文章主要代码与文字...

  • python Mock的使用(1)

    什么是mock? mock在翻译过来有模拟的意思。这里要介绍的mock是辅助单元测试的一个模块。它允许您用模拟对象...

  • 优雅的模拟测试框架mock,用于Java的单元测试

    什么是mock ? mock在翻译过来是模拟的意思。这里要介绍的mock是辅助单元测试的一个模块。它允许你用模拟对...

  • Python unittest.mock基本使用

    什么是mock? mock在翻译过来有模拟的意思。这里要介绍的mock是辅助单元测试的一个模块。它允许您用模拟对象...

网友评论

      本文标题:go 单元测试(二)mock

      本文链接:https://www.haomeiwen.com/subject/obspgrtx.html