既然我們已經有了 db.Store
interface
,我們可以使用 gomock
生成 mock
interface
。
首先,我將在 db
套件內創建一個新的 mock
文件夾。接著,打開終端機並執行:
mkdir -p db/mock
mockgen -help
mockgen
提供了兩種方式生成mocks:
mockgen
使用反射自動完成。選擇使用 Reflect mode 並執行以下命令:
Store Interface
的導入路徑 (github.com/Kcih4518/simpleBank_2023/db/sqlc
)。Interface Name
,即 Store
。destination
是指定生成輸出文件的目的地: db/mock/store.go
package
指定的package
name
(mockdb
)mockgen -build_flags=--mod=mod -destination db/mock/store.go -package mockdb github.com/Kcih4518/simpleBank_2023/db/sqlc Store
回到 Visual Studio Code,我們可以看到在 db/mock
文件夾內生成了一個新的 store.go
文件。
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/Kcih4518/simpleBank_2023/db/sqlc (interfaces: Store)
// Package mockdb is a generated GoMock package.
package mockdb
import (
context "context"
reflect "reflect"
db "github.com/Kcih4518/simpleBank_2023/db/sqlc"
gomock "github.com/golang/mock/gomock"
)
// MockStore is a mock of Store interface.
type MockStore struct {
ctrl *gomock.Controller
recorder *MockStoreMockRecorder
}
// MockStoreMockRecorder is the mock recorder for MockStore.
type MockStoreMockRecorder struct {
mock *MockStore
}
// NewMockStore creates a new mock instance.
func NewMockStore(ctrl *gomock.Controller) *MockStore {
mock := &MockStore{ctrl: ctrl}
mock.recorder = &MockStoreMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockStore) EXPECT() *MockStoreMockRecorder {
return m.recorder
}
...
這個文件中有兩個重要的結構:MockStore
和 MockStoreMockRecorder
。
MockStore
:實現了 Store Interface
的所有必需功能。MockStoreMockRecorder
:用於建立stubs,可以指定應該呼叫 AddAccountBalance()
函數多少次,以及參數的值。// AddAccountBalance mocks base method.
func (m *MockStore) AddAccountBalance(arg0 context.Context, arg1 db.AddAccountBalanceParams) (db.Account, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAccountBalance", arg0, arg1)
ret0, _ := ret[0].(db.Account)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddAccountBalance indicates an expected call of AddAccountBalance.
func (mr *MockStoreMockRecorder) AddAccountBalance(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAccountBalance", reflect.TypeOf((*MockStore)(nil).AddAccountBalance), arg0, arg1)
}
在開始使用新生成的 MockStore
寫API測試之前,我會在 Makefile
中添加一個新的 mock 命令,這樣我們可以隨時重新生成代碼。
mock:
mockgen -build_flags=--mod=mod -destination db/mock/store.go -package mockdb github.com/Kcih4518/simpleBank_2023/db/sqlc Store
.PHONY: postgres createdb dropdb migrateup migratedown sqlc test server mock
現在,每當我們想重新生成 mock store,我們可以簡單地在終端機中運行 make mock
。
MockStore Struct
是Store Interface
的implementation
?
為了確定 MockStore
是否實現了 Store
Interface
的每個方法,您需要將 MockStore
的方法與 Store
介面中定義的方法進行比較。如果 MockStore
對於 Store
中的每個方法都有相應的方法,且每個方法都有正確的Signature
(函數名稱、它的參數類型列表和它的返回值類型),那麼 MockStore
就完全實現了 Store
介面。
db/sqlc/store.go
type Store interface {
Querier
TransferTx(ctx context.Context, arg TransferTxParams) (TransferTxResult, error)
}
db/sqlc/querier.go
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.20.0
package db
import (
"context"
)
type Querier interface {
AddAccountBalance(ctx context.Context, arg AddAccountBalanceParams) (Account, error)
CreateAccount(ctx context.Context, arg CreateAccountParams) (Account, error)
CreateEntry(ctx context.Context, arg CreateEntryParams) (Entry, error)
CreateTransfer(ctx context.Context, arg CreateTransferParams) (Transfer, error)
DeleteAccount(ctx context.Context, id int64) error
GetAccount(ctx context.Context, id int64) (Account, error)
GetAccountForUpdate(ctx context.Context, id int64) (Account, error)
GetEntry(ctx context.Context, id int64) (Entry, error)
GetTransfer(ctx context.Context, id int64) (Transfer, error)
ListAccounts(ctx context.Context, arg ListAccountsParams) ([]Account, error)
ListEntries(ctx context.Context, arg ListEntriesParams) ([]Entry, error)
ListTransfers(ctx context.Context, arg ListTransfersParams) ([]Transfer, error)
UpdateAccount(ctx context.Context, arg UpdateAccountParams) (Account, error)
}
var _ Querier = (*Queries)(nil)
db/mock/store.go
func (m *MockStore) AddAccountBalance(arg0 context.Context, arg1 db.AddAccountBalanceParams) (db.Account, error)
func (m *MockStore) CreateAccount(arg0 context.Context, arg1 db.CreateAccountParams) (db.Account, error)
func (m *MockStore) CreateTransfer(arg0 context.Context, arg1 db.CreateTransferParams) (db.Transfer, error)
func (m *MockStore) TransferTx(arg0 context.Context, arg1 db.TransferTxParams) (db.TransferTxResult, error)
...