iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
自我挑戰組

2023年度學習分享系列 第 6

mock工具介紹

  • 分享至 

  • xImage
  •  

文章未來將更新於:
https://kevinyay945.com/golang-project-design/2023/introduce-golang-mock-tool/

這次我們使用的是mock這個工具幫我們快速的模擬需要的interface

值得一提的是,因為這次要撰寫文章特別又回去看了文件,才發先原先golang提供的mock的github被archive了,現在是由uber來接管這個專案,所以如果未來大家要使用,要特別注意,不要用到archive的連結了
舊的: https://github.com/golang/mock
新的: https://github.com/uber-go/mock

要使用這個工具,要先瞭解他的原理
他的主要邏輯是,他可以針對你目前的interface透過工具的幫忙,自動產生出可以implement相對應的資料的內容
比如說,我先宣告了一個FileStorer的interface

package application

type FileStorer interface {
	UploadAsset(filename string, i []byte, s string) (file domain.CloudFile, err error)
	GetPreviewLink(asset domain.CloudFile) (link string, err error)
}

接著透過mock工具提供的cli

打上

mockgen -destination=file_store_mock.go -package=application -self_package=2023_asset_management/application . FileStorer

透過這個指令,他就可以幫你產生相對應的檔案

// Code generated by MockGen. DO NOT EDIT.
// Source: 2023_asset_management/application (interfaces: FileStorer)

// Package application is a generated GoMock package.
package application

import (
	domain "2023_asset_management/domain"
	reflect "reflect"

	gomock "go.uber.org/mock/gomock"
)

// MockFileStorer is a mock of FileStorer interface.
type MockFileStorer struct {
	ctrl     *gomock.Controller
	recorder *MockFileStorerMockRecorder
}

// MockFileStorerMockRecorder is the mock recorder for MockFileStorer.
type MockFileStorerMockRecorder struct {
	mock *MockFileStorer
}

// NewMockFileStorer creates a new mock instance.
func NewMockFileStorer(ctrl *gomock.Controller) *MockFileStorer {
	mock := &MockFileStorer{ctrl: ctrl}
	mock.recorder = &MockFileStorerMockRecorder{mock}
	return mock
}

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

// GetPreviewLink mocks base method.
func (m *MockFileStorer) GetPreviewLink(arg0 domain.CloudFile) (string, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetPreviewLink", arg0)
	ret0, _ := ret[0].(string)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// UploadAsset mocks base method.
func (m *MockFileStorer) UploadAsset(arg0 string, arg1 []byte, arg2 string) (domain.CloudFile, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UploadAsset", arg0, arg1, arg2)
	ret0, _ := ret[0].(domain.CloudFile)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

他可以自動產生一個implement你指定interface的struct,並提供你在測試的時候需要的功能

當然,因為在每個interface下你都會需要這段工具,所以這時候就要使用go提供的一個工具
generate

當你在程式碼中放上這樣的一段內容

//go:generate mockgen -destination=file_store_mock.go -package=application -self_package=2023_asset_management/application . FileStorer
type FileStorer interface {
	UploadAsset(filename string, i []byte, s string) (file domain.CloudFile, err error)
	GetPreviewLink(asset domain.CloudFile) (link string, err error)
}

並且透過shell來執行以下指令

go generate ./filestore.go

如此一來,他就會去掃描你指定的這個檔案有沒有使用go:generate這個tag,並且執行後面所撰寫的程式碼內容

如此一來,就算之後有大量的interface需要產生mock file,也可以透過go generate來幫忙快速產生

更棒的是,go generate還有提供另一個方式,可以讓你可以你當前目錄下的所有檔案
方法如下

go generate ./...

如此一來,你只要整個專案都有放上go:generate的內容,都會被順利執行,相當的方便


上一篇
DDD規劃及參考
下一篇
Constructor與DI
系列文
2023年度學習分享30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言