4

Golang常见mock库小结

 2 years ago
source link: http://vearne.cc/archives/39542
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc

本文是一篇对mock库的小结。

2. 怎么理解mock这件事

2.1 为什么需要mock

最常见的场景是,一个服务B和它依赖的上游微服务A同时启动开发。为了加快开发速度,服务B不可能等到服务A开发完,在启动开发。因此服务A和服务B约定它们之间交互的接口,然后就可以启动开发了。

服务B为了验证自身的业务逻辑,它需要mock一个A服务(只需要mock相关接口)。但是mock A服务本身可能也比较麻烦,涉及到网络IO,端口占用等等。所以进一步的,我们只需把与服务A的交互封装到一个interface中。这样只需要mock这个interface就可以了。

2.2 示例

mock最常见的场景是用于单元测试
完整示例
biz.go

type People interface {
    Say(s string) string
}

// 业务逻辑
func BizLogic(p People, s string) string {
    return "People Say:" + p.Say(s)
}

在单元测试中,验证我们的业务逻辑
biz_test.go

import (
    "github.com/stretchr/testify/mock"
    "testing"
)
type FakePeople struct {
    mock.Mock
}

func (m *FakePeople) Say(str string) string {
    args := m.Called(str)
    return args.String(0)
}

func TestSomething(t *testing.T) {

    // create an instance of our test object
    testObj := new(FakePeople)

    // setup expectations
    testObj.On("Say", "Jack").Return("hello Jack")
    testObj.On("Say", "Lucy").Return("hello Lucy")

    // call the code we are testing
    expected := "People Say:hello Jack"
    got := BizLogic(testObj, "Jack")
    if expected == got {
        t.Logf("got = %v; expected = %v", got, expected)
    } else {
        t.Errorf("got = %v; expected = %v", got, expected)
    }
}

2.3 实现原理

FakePeople是一个实现了接口People的类。有时候它也被称为Stub。它可以被理解为一个占位符,替代对真实的服务交互过程。

我们为针对它的请求预设了返回结果
每一组 请求+return 在stretchr/testify中被称为call

mock.go

type Call struct {
    Parent *Mock

    // The name of the method that was or will be called.
    Method string

    // Holds the arguments of the method.
    Arguments Arguments

    // Holds the arguments that should be returned when
    // this method is called.
    ReturnArguments Arguments
    ...

ExpectedCalls

methodName methodArguments ReturnArguments

“Say” [“Jack”] [“hello Jack”]

“Say” [“Lucy”] [“hello Lucy”]

p.Say(s)

会在预设的ExpectedCalls中进行查找,看是否有匹配的call,有就返回对应的ReturnArguments, 否则会抛出异常。

3. 三种常见的mock库

3.1 仓库

3.2 支持范围

library interface function member method function variable

golang/mock ✅

|

stretchr/testify ✅agiledragon/gomonkey ✅✅✅✅

3.3 小结

其实从实现上讲golang/mockstretchr/testify属于同一类,都只支持interface
golang/mock相比stretchr/testify功能更强大,提供mockgen工具可以针对interface通过反射自动生成stub。对应 2.2情况,它可以自动生成实现接口People的类FakePeople

agiledragon/gomonkey是在编译阶段替换了符号表中符号对应的地址,因此它的支持范围更大。

微信支付码


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK