最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go語言中GoMock的實現(xiàn)

 更新時間:2025年11月14日 09:21:15   作者:-睡到自然醒~  
GoMock是一個Go框架,它與內置的測試包整合得很好,并在單元測試時提供了靈活性,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

GoMock是一個Go框架。它與內置的測試包整合得很好,并在單元測試時提供了靈活性。正如我們所知,對具有外部資源(數(shù)據(jù)庫、網絡和文件)或依賴關系的代碼進行單元測試總是很麻煩。

安裝

為了使用GoMock,我們需要安裝gomock包github.com/golang/mock/gomock和mockgen代碼生成工具github.com/golang/mock/mockgen。使用這個命令行:

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

GoMock的使用遵循四個基本步驟:

  • 使用mockgen為你想模擬的接口生成一個模擬對象。
  • 在測試部分,創(chuàng)建一個gomock.Controller的實例,并把它傳遞給你的mock對象的構造函數(shù)以獲得一個mock對象。
  • 在mock上調用EXPECT()來設置期望值和返回值。
  • 在模擬控制器上調用Finish()來斷言模擬對象的期望。

開始

讓我們創(chuàng)建一個這樣的文件夾(本代碼在 go1.16.15 版本下執(zhí)行)

gomock_test
├── doer
│ └── doer.go
├── mocks
│ └── mock_doer.go
└── user
  ├── user.go
  └── user_test.go

doer/doer.go

package doer

type Doer interface {
  DoSomething(int, string) error
  SaySomething(string) string
}

那么這里是我們在模擬Doer接口時要測試的代碼。

user/user.go

package user

import "gomock_test/doer"

const (
	filtered   = "OK"
	unfiltered = "spam"
	Nice       = "nice"
	Bad        = "bad"
)

type User struct {
	// struct while mocking the doer interface
	Doer doer.Doer
}

// method Use using it
func (u *User) Use() error {
	return u.Doer.DoSomething(123, "Hello GoMock")
}

func (u *User) SaySomething(num int) string {
	if num == 3 {
		return u.Doer.SaySomething(unfiltered)
	}
	return u.Doer.SaySomething(filtered)
}

type Student struct{}

func (s *Student) DoSomething(_ int, _ string) error {
	panic("not implemented") // TODO: Implement
}

func (s *Student) SaySomething(kata string) string {
	if kata == filtered {
		return Nice
	}
	return Bad
}

我們將把Doer的模擬放在一個包mocks中。我們首先創(chuàng)建一個包含我們的模擬實現(xiàn)的目錄mocks,然后在doer包上運行mockgen:

mockgen -destination=../mocks/mock_doer.go -package=mocks gomock_test/doer Doer

NOTE: 在執(zhí)行這步的時候,會報錯:Failed to format generated source code: mocks/mock_doer.go:5:15: expected ‘;’, found '.’ 這個時候,我們只需要將打印出來的代碼復制到我們對應的文件中即可。

當有大量的接口/包需要模擬時,為每個包和接口運行mockgen是一種烏托邦。為了緩解這個問題,可以將mockgen命令與go:generate放在一起。

go:generate mockgen -destination=../mocks/mock_doer.go -package=mocks gomock_test/doer Doer

我們必須自己創(chuàng)建目錄模擬,因為GoMock不會為我們這樣做,而是會以錯誤退出。

  • destination=…/mocks/mock_doer.go : 把生成的mocks放在這個路徑下。
  • -package=mocks : 把生成的mocks放在這個包里
  • gomock_test/doer : 為這個包生成mocks。
  • Doer : 為這個接口生成mocks(必填),因為我們需要指定哪個接口來生成mocks。(如果需要的話,可以用逗號分隔的列表來指定多個接口。例如,Doer1, Doer2)

因為我們對mockgen的調用在我們的項目中放置了一個文件mocks/mock_doer.go。這就是這樣一個生成的mock實現(xiàn)的樣子:

// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/timliudream/go-test/gomock_test/doer (interfaces: Doer)

// Package github.com/timliudream/go-test/gomock_test/mocks is a generated GoMock package.
package mocks

import (
	gomock "github.com/golang/mock/gomock"
	reflect "reflect"
)

// MockDoer is a mock of Doer interface.
type MockDoer struct {
	ctrl     *gomock.Controller
	recorder *MockDoerMockRecorder
}

// MockDoerMockRecorder is the mock recorder for MockDoer.
type MockDoerMockRecorder struct {
	mock *MockDoer
}

// NewMockDoer creates a new mock instance.
func NewMockDoer(ctrl *gomock.Controller) *MockDoer {
	mock := &MockDoer{ctrl: ctrl}
	mock.recorder = &MockDoerMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDoer) EXPECT() *MockDoerMockRecorder {
	return m.recorder
}

// DoSomething mocks base method.
func (m *MockDoer) DoSomething(arg0 int, arg1 string) error {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DoSomething", arg0, arg1)
	ret0, _ := ret[0].(error)
	return ret0
}

// DoSomething indicates an expected call of DoSomething.
func (mr *MockDoerMockRecorder) DoSomething(arg0, arg1 interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DoSomething", reflect.TypeOf((*MockDoer)(nil).DoSomething), arg0, arg1)
}

// SaySomething mocks base method.
func (m *MockDoer) SaySomething(arg0 string) string {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "SaySomething", arg0)
	ret0, _ := ret[0].(string)
	return ret0
}

// SaySomething indicates an expected call of SaySomething.
func (mr *MockDoerMockRecorder) SaySomething(arg0 interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaySomething", reflect.TypeOf((*MockDoer)(nil).SaySomething), arg0)
}

接下來,我們在測試中定義一個模擬控制器。一個模擬控制器負責跟蹤和斷言其相關模擬對象的期望。我們可以通過傳遞一個*testing.T類型的值給它的構造函數(shù)來獲得一個模擬控制器,并使用它來構造一個Doer接口的模擬對象。

//core of gomock
mockCtrl := gomock.NewController(t)
//used to trigger final assertions. if its ignored, mocking assertions will never fail
defer mockCtrl.Finish()
// create a new mock object, passing the controller instance as parameter
// for a newly created mock object it will accept any input and outpuite
// need to define its behavior with the method expect
mockDoer := mocks.NewMockDoer(mockCtrl)

使用參數(shù)匹配器

在GoMock中,一個參數(shù)可以被期望有一個固定的值,也可以被期望與一個謂詞(稱為匹配器)相匹配。匹配器用于表示被模擬方法的預期參數(shù)范圍。下列匹配器在Gomock中被預先定義了:

  • gomock.Any() : 匹配任何值(任何類型)。
  • gomock.Eq(x) : 使用反射來匹配與x深度相等的值。
  • gomock.Nil() : 匹配nil

user/user_test.go

package user

import (
	"fmt"
	"github.com/golang/mock/gomock"
	"gomock_test/mocks"
	"testing"
)

func TestUse(t *testing.T) {
	//core of gomock
	mockCtrl := gomock.NewController(t)
	//used to trigger final assertions. if its ignored, mocking assertions will never fail
	defer mockCtrl.Finish()
	// create a new mock object, passing the controller instance as parameter
	// for a newly created mock object it will accept any input and outpuite
	// need to define its behavior with the method expect
	mockDoer := mocks.NewMockDoer(mockCtrl)
	testUser := &User{Doer: mockDoer}
	//
	// Expect Do to be called once with 123 and "Hello GoMock" as parameters, and return nil from the mocked call.
	mockDoer.EXPECT().DoSomething(123, "Hello GoMock").Return(nil).Times(1)
	fmt.Println(testUser.Use())
	fmt.Println()
}

func TestUser_SaySomething(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()
	mockDoer := mocks.NewMockDoer(mockCtrl)
	user := User{
		Doer: mockDoer,
	}
	type args struct {
		num int
	}
	tests := []struct {
		name    string
		args    args
		want    string
		expect  func()
		wantErr bool
	}{
		{
			name: "Positive test case 1",
			expect: func() {
				mockDoer.EXPECT().SaySomething("spam").Return("bad")
			},
			args:    args{num: 3},
			wantErr: false,
			want:    "bad",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			tt.expect()
			if got := user.SaySomething(tt.args.num); (got != tt.want) != tt.wantErr {
				fmt.Println("gott :", got)
				t.Errorf("User.SaySomething() = %v, want %v", got, tt.want)
			}
		})
	}
}

而單元測試的結果將是這樣的:

=== RUN   TestUser_SaySomething
=== RUN   TestUser_SaySomething/Positive_test_case_1
--- PASS: TestUser_SaySomething (0.00s)
    --- PASS: TestUser_SaySomething/Positive_test_case_1 (0.00s)
PASS
ok      github.com/tokopedia/go_learning/udemy/pzn/gomock_test/user     1.100s

到此這篇關于go語言中GoMock的實現(xiàn)的文章就介紹到這了,更多相關go語言 GoMock內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 深入解析golang編程中函數(shù)的用法

    深入解析golang編程中函數(shù)的用法

    這篇文章主要介紹了golang編程中函數(shù)的用法,是Go語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-10-10
  • Golang操作Kafka的實現(xiàn)示例

    Golang操作Kafka的實現(xiàn)示例

    本文主要介紹了Golang操作Kafka的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • Go語言異常處理(Panic和recovering)用法詳解

    Go語言異常處理(Panic和recovering)用法詳解

    異常處理是程序健壯性的關鍵,往往開發(fā)人員的開發(fā)經驗的多少從異常部分處理上就能得到體現(xiàn)。Go語言中沒有Try?Catch?Exception機制,但是提供了panic-and-recover機制,本文就來詳細講講他們的用法
    2022-07-07
  • 一文總結Go語言切片核心知識點和坑

    一文總結Go語言切片核心知識點和坑

    都說Go的切片用起來絲滑得很,Java中的List怎么用,切片就怎么用,作為曾經的Java選手,因為切片的使用不得當,喜提缺陷若干,本文就給大家總結一下Go語言切片核心知識點和坑,需要的朋友可以參考下
    2023-06-06
  • go?pprof?的使用操作代碼

    go?pprof?的使用操作代碼

    pprof 是 go 中進行性能分析的工具,可以提供可視化數(shù)據(jù)查看,這篇文章主要介紹了go?pprof?的使用操作,需要的朋友可以參考下
    2022-09-09
  • Go使用defer函數(shù)要注意的幾個點

    Go使用defer函數(shù)要注意的幾個點

    這篇文章主要介紹了Go使用defer函數(shù)要注意的幾個點,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • Go語言中的內存布局詳解

    Go語言中的內存布局詳解

    這篇文章主要給大家介紹了Go語言中的內存布局,那么本文中將嘗試解釋Go如何在內存中構建結構體,以及結構體在字節(jié)和比特位方面是什么樣子。 有需要的朋友們可以參考借鑒,感興趣的朋友們下面來跟著小編一起學習學習吧。
    2016-11-11
  • Go緩沖channel和非緩沖channel的區(qū)別說明

    Go緩沖channel和非緩沖channel的區(qū)別說明

    這篇文章主要介紹了Go緩沖channel和非緩沖channel的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go語言中使用Swagger 生成 API 文檔及常見問題解決

    Go語言中使用Swagger 生成 API 文檔及常見問題解決

    Swagger 是一個規(guī)范和完整的框架,用于生成、描述、調用和可視化 RESTful風格的Web服務,本文就來詳細的介紹一下如何實現(xiàn)Go語言中使用Swagger 生成 API 文檔,感興趣的可以了解一下
    2026-01-01
  • Go中select多路復用的實現(xiàn)示例

    Go中select多路復用的實現(xiàn)示例

    Go的select用于多通道通信,實現(xiàn)多路復用,支持隨機選擇、超時控制及非阻塞操作,建議合理使用以避免協(xié)程泄漏和死循環(huán),感興趣的可以了解一下
    2025-08-08

最新評論

鄱阳县| 金堂县| 繁昌县| 政和县| 乐清市| 丽水市| 喀什市| 奉化市| 连云港市| 桃江县| 巴东县| 比如县| 宁德市| 凉城县| 军事| 玉树县| 贡山| 墨竹工卡县| 马关县| 孝昌县| 东辽县| 三江| 北京市| 邛崃市| 白城市| 涿鹿县| 伊宁县| 佛冈县| 唐河县| 建湖县| 思茅市| 弋阳县| 青铜峡市| 鲁甸县| 依安县| 长宁县| 深州市| 绥宁县| 拜城县| 芜湖县| 云安县|