golang基礎-單元測試與mock

golang 單元測試

單元測試介紹

爲了保證代碼的質量,不少公司都會要求寫單元測試。這裏介紹兩個指標,git

  1. 函數覆蓋率:函數調用個數/函數個數,一般要求100%
  2. 行覆蓋率:走到的行的個數/總函數,一般要求>60%

經過單元測試,咱們能夠針對不一樣場景進行測試,是研發本身對質量的把控。 筆者目前所在的公司對單元測試要求很高,而且有替代測試的趨勢。github

go test

  • go的test通常以xxx_test.go爲文件名,xxx並無特別要求是要實測的文件名
  • TestMain做爲初始化test
  • Testxxx(t* testing.T)
  • go test 便可運行單元測試
  • go test --v --test.run funcName 能夠指定單測某個方法

建立一個client包進行示例,包結構以下golang

.
├── client.go
├── client_test.go
複製代碼
func TestUser(t *testing.T) {
    var u = &User{Age: 15, Name: "alice"}
    if u.Age != 15 {
        t.Error("age err")
    }   
    if u.Name != "bob" {
        t.Error("name err")
    }   
}
複製代碼

因爲Name不符合預期,則會有以下提示bash

--- FAIL: TestUser (0.00s)
    client_test.go:28: name err
FAIL
exit status 1
FAIL	test/mocktest	0.005s
複製代碼

go convey

goconvey能夠很好的支持setup和teardown,goconvey能夠在運行單個測試用例前都進行一次狀態初始化和銷燬。goconvey還有不少已經定義好了的可以直接使用的assert函數,而且能夠自定義assert函數。 經常使用的assert以下:函數

var (
    ShouldEqual          = assertions.ShouldEqual
    ShouldNotEqual       = assertions.ShouldNotEqual

    ShouldBeGreaterThan          = assertions.ShouldBeGreaterThan
    ShouldBeGreaterThanOrEqualTo = assertions.ShouldBeGreaterThanOrEqualTo
    ShouldBeLessThan             = assertions.ShouldBeLessThan
    ShouldBeLessThanOrEqualTo    = assertions.ShouldBeLessThanOrEqualTo
    ShouldBeBetween              = assertions.ShouldBeBetween
    ShouldNotBeBetween           = assertions.ShouldNotBeBetween
    ShouldBeBetweenOrEqual       = assertions.ShouldBeBetweenOrEqual
    ShouldNotBeBetweenOrEqual    = assertions.ShouldNotBeBetweenOrEqual
    ShouldContainSubstring    = assertions.ShouldContainSubstring
    ShouldNotContainSubstring = assertions.ShouldNotContainSubstring

    ShouldPanic        = assertions.ShouldPanic
    ShouldBeError      = assertions.ShouldBeError
)
複製代碼

使用舉例:微服務

func TestUser(t *testing.T) {
    convey.Convey("TestUser", t, func() {
        var u = &User{Age: 15, Name: "alice"}
        convey.So(u.Age, convey.ShouldEqual, 15) 
        convey.So(u.Name, convey.ShouldEqual, "bob")
    })  
}
複製代碼

因爲Name不符合預期,會出現以下提示單元測試

Line 30:
  Expected: 'bob'
  Actual:   'alice'
  (Should be equal)
複製代碼

mock

什麼是mock

單元測試的時候,若是流程中有第三方依賴怎麼辦?好比當貸款支付的時候,須要用戶的額度,而額度信息存在於另外一個微服務,須要rpc拉取。爲了解決這種場景,咱們可使用mock這種方式。簡單來講,mock就是能指定依賴接口的輸入 輸出,能夠理解爲提早插入的固定數據,如此,流程就能正常跑起來。測試

使用mockery進行mock

限制:ui

  • 只能針對接口進行mock

使用流程spa

  • 安裝mockery:go get github.com/vektra/mockery/.../
  • mockery -name=接口名,生成mocks目錄。

rpc接口定義,接口實現

client.go:

package rpc 

//go:generate mockery -name=Client

type Client interface {
    Get(key string) (data interface{}, err error)
}

type ClientImpl struct {
    Ct Client
}

func (p *ClientImpl) Get(key string) (data interface{}, err error) {
    if mockCondition  {
        return p.Ct.Get(key)
    }
    // real logic
}
複製代碼

client_test.go

package rpc 

import (
    "fmt"
    "test/mocktest/mocks"
    "testing"
)

type User struct {
    Age  int 
    Name string
}

func TestMock(t *testing.T) {
    convey.Convey("TestMock", t, func() {
        mc := &mocks.Client{}
        var u = &User{Age: 15, Name: "alice"}
        mc.On("Get", "alice").Return(u, nil)
        ci.Ct = mc
        data, err := ci.Get("alice")
        convey.So(data.Age, convey.ShouldEqual, 15)
    }
}
複製代碼
相關文章
相關標籤/搜索