https://zenn.dev/sanpo_shiho/articles/01da627ead98f5

og-base_z4sxah.png

この記事は 3/27 に開催されたCAMPHOR- DAY内で発表した内容を元にした記事です。

アーカイブはこちら(共有してるスライドの画面が黄色くなっていることは終わってから知りました🥺)

この記事では gomock や mockgen の基本的な使用方法から、 gomock の内部の動きまでを紹介します。この記事を読み終わったあなたは思わずgomock 完全に理解した と言っていることでしょう。

基本的にGoの文法を知っていればgomock自体を知らなくても理解できるような説明にしているつもりです。

この記事ではv1.5.0の仕様をもとに話しています。

golang/mock(gomock) とは

go 公式が出しているインターフェース定義からモックの生成を行うことができるライブラリです。

生成したモックを扱うパッケージも含まれます。

この先の説明では gomock と呼ぶことにします

モックの扱い方を理解する

モックを生成してみる

mockgenに関して詳しくは後述しますが、以下のようなコマンドでモックが生成されます。

mockgen -source=user.go -destination=./mock

これ以降は以下のインターフェースを元に生成されたモックを元に説明を行います。

以下のようなモックが生成されます(ここでは詳しく読む必要はないので読み飛ばしてください)

// Code generated by MockGen. DO NOT EDIT.
// Source: user.go

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

import (
    entity "github.com/camphor-/relaym-server/domain/entity"
    gomock "github.com/golang/mock/gomock"
    reflect "reflect"
)

// MockUser is a mock of User interface
type MockUser struct {
    ctrl     *gomock.Controller
    recorder *MockUserMockRecorder
}

// MockUserMockRecorder is the mock recorder for MockUser
type MockUserMockRecorder struct {
    mock *MockUser
}

// NewMockUser creates a new mock instance
func NewMockUser(ctrl *gomock.Controller) *MockUser {
    mock := &MockUser{ctrl: ctrl}
    mock.recorder = &MockUserMockRecorder{mock}
    return mock
}

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

// Update mocks base method
func (m *MockUser) Update(user *entity.User) error {
    m.ctrl.T.Helper()
    ret := m.ctrl.Call(m, "Update", user)
    ret0, _ := ret[0].(error)
    return ret0
}

// Update indicates an expected call of Update
func (mr *MockUserMockRecorder) Update(user interface{}) *gomock.Call {
    mr.mock.ctrl.T.Helper()
    return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUser)(nil).Update), user)
}

生成されたモックを見てみる