概要
gomock
を使用してio.Reader
を引数に取るメソッドをモックするテストを書きました。
公式ライブラリではio.Reader
を使用するメソッドが多く存在し、利用する場面でもそれらをそのまま受け渡したいケースも時には存在すると思います。検索をすると自作のmatcher
を使用するなど複雑なやり方が載っていますがstrings.NewReader()
を使用してio.Reader
型の引数を作成することで通常の引数の確認と同様にテストを作成できました。備忘録を兼ねて投稿します。
方法
下記のようなメソッドがあったとします。mockgen
を使用することでモックを作成しています。
sample_repository.go
package usecase
import "io"
// go:generate mockgen -source=$GOFILE -package=$GOPACKAGE -destination=mock_$GOFILE
type SampleRepository interface {
Read(r io.Reader) error
}
上記のメソッドを以下のように使用しているとします。
sample_interactor.go
package usecase
import "strings"
type sampleService struct {
sampleRepository SampleRepository
}
func NewSampleService(sr SampleRepository) sampleService {
return sampleService{sampleRepository: sr}
}
func (ss *sampleService) Exec(text string) {
r := strings.NewReader(text)
ss.sampleRepository.Read(r)
}
テストはこのように書けます。strings.NewReader()
はio.Reader
型を返却するので、テストを記載することが可能です。
sample_interactor_test.go
package usecase
import (
"strings"
"testing"
"github.com/golang/mock/gomock"
)
const testString = "hoge"
func TestExec(t *testing.T) {
tests := []struct {
name string
setup func(m *MockSampleRepository)
}{
{
name: "Test the argument",
setup: func(m *MockSampleRepository) {
// 引数を指定してモックが使用されることを宣言
m.EXPECT().Read(strings.NewReader(testString))
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// gomockのコントローラーを作成
ctrl := gomock.NewController(t)
// SampleRepositoryのモックを作成
mock := NewMockSampleRepository(ctrl)
// モックをセットアップ
tt.setup(mock)
// SampleRepositoryを使用してSampleServiceを作成
sampleService := NewSampleService(mock)
// テスト対象の関数を実行
sampleService.Exec(testString)
})
}
}
まとめ
io.Reader
を検証するのに少し身構えてしまっていましたが、通常のモックのテストと同様に書けることがわかりました。