Go

https://github.com/golang/mock

Goのinterfaceからmockを生成するツール + 生成したコードをテストコード内で利用するためのライブラリ

s3api.go

type S3Api interface {
	DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error)
	GetObject(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error)
	ListObjectsV2(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error)
}
$ go install github.com/golang/mock/mockgen@latest
$ mockgen -source=repository/s3api.go -destination=repository/mock/s3api.go

ソースファイル内にgo:generateディレクティブを書くことで、 go generate コマンドで生成されるようになる

//go:generate mockgen -source=$GOFILE -destination=../$GOPACKAGE/mock/$GOFILE

テストコード内での使い方

import (
	"context"
	"testing"
 
	mock_repository "my/repository/mock"
	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
)
 
func TestService(t *testing.T) {
	// gomock Controllerを初期化
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()
 
	// モックメソッドの挙動を指定
	ctx := context.Background()
	repoMock := mock_repository.NewMockS3Api(ctrl)
	repoMock.EXPECT().GetObject(ctx, &s3.GetObjectInput{}. nil).Return(&s3.GetObjectOutput{}, nil)
 
	// モックを注入
	srv := Service{
		repo: repoMock,
	}
 
	// テストメソッドを実行
	ok, err := srv.IsExistEntity(1)
	if err != nil {
		t.Errorf("予期せぬエラー: %v", err)
	} else if !ok {
		t.Errorf("期待: %v, 実際: %v", true, ok)
	}
}

gomockhandler

Goで大量のモックをより統一的に管理し、もっと高速に生成したい!そうだ!!gomockhandlerを使おう!! | メルカリエンジニアリング

go install github.com/sanposhiho/gomockhandler@latest

testify、mockery

https://github.com/stretchr/testify にもmockパッケージが存在する。

mockの作成は mockery を使う。 gomockに比べた優位性を書いてくれているが正直好みでって感じ。testifyにどっぷり浸かるならこちらでいいと思う https://vektra.github.io/mockery/#why-use-mockery-over-gomock

mock作成

以下のコマンドで、dir配下のすべてのinterfaceに対してmockが作成される。 --inpackage をつけることでinterfaceと同じパッケージに mock_<interface名>.go で作成される。

$ mockery --all --dir=src --inpackage

参考