GoMock入門:初心者向けの使い方とテストの書き方
はじめに
GoMockは、Go言語でモック(Mock)を使ったテストを簡単に書けるようにするライブラリです。
外部APIやデータベースに依存するコードをテストする際、GoMockを使うことで依存関係を分離し、効率的なユニットテストが実現できます。
本記事では、GoMockの基本的な使い方を中心に、以下の内容を解説します。
対象読者
- Go言語のテストを学び始めた方
- 外部APIやDBに依存しないテストを書きたい方
- GoMockを使ってモックを作成したい方
目次
- GoMockとは?
- インストール方法
- 基本的な使い方
- モックの生成
- モックの設定
- モックの検証
- 実践:GoMockを使ったユニットテスト
1. そもそもGoMockとは?
GoMockは、Go言語用のモック生成ライブラリで、以下の特徴があります。
- 依存関係を分離して、テスト対象の関数やメソッドだけを検証できる。
- gomock.Controllerを使って、モックの動作を設定・検証できる。
- Mockgenというツールを使って、インターフェースからモックコードを自動生成 できる。
2. インストール方法
1. GoMockとMockgenのインストール
以下のコマンドを実行して、GoMockとMockgenをインストールします。
go install github.com/golang/mock/mockgen@latest
.zshrcまたは.bash_profileに以下を追加して、環境変数PATHを設定します。
export PATH=$PATH:$(go env GOPATH)/bin
設定を反映させるために、以下を実行します。
source ~/.zshrc # Zshを使用している場合
source ~/.bash_profile # Bashを使用している場合
2. Go Modulesに追加
go.modにGoMockを追加します。
go get github.com/golang/mock/gomock
3. 基本的な使い方
3.1 モックの生成
Mockgenを使って、インターフェースからモックを自動生成します。
今回は、UserRepositoryインターフェースをモック化してみます。
user.go
package example
type User struct {
ID int
Name string
}
type UserRepository interface {
GetUser(id int) (*User, error)
}
以下のコマンドを実行して、モックを生成します。
mockgen -source=user.go -destination=mock_user.go -package=example
-
-source: モックを生成する元のインターフェースを含むファイル -
-destination: 生成されるモックのファイル名 -
-package: モックを含むパッケージ名
3.2 モックの設定
gomock.Controllerを使って、モックの動作を設定します。
user_test.go
package example_test
import (
"errors"
"testing"
"github.com/golang/mock/gomock"
"example"
)
func TestGetUser_Success(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockRepo := example.NewMockUserRepository(ctrl)
mockRepo.EXPECT().GetUser(1).Return(&example.User{ID: 1, Name: "John"}, nil)
user, err := mockRepo.GetUser(1)
if err != nil {
t.Fatal("expected no error, but got", err)
}
if user.Name != "John" {
t.Fatal("expected user name to be John, but got", user.Name)
}
}
3.3 モックの検証
-
EXPECT()を使って、モックの動作を設定 -
Return()を使って、モックの返り値を設定 -
ctrl.Finish()で、呼び出し回数の検証 を行う
4. 実践:GoMockを使ったユニットテスト
GoMockを使って、外部依存を分離したユニットテストを実装します。
今回は、UserServiceがUserRepositoryに依存しているケースをテストします。
4.1 UserServiceの実装
user_service.go
package example
import "errors"
type UserService struct {
repo UserRepository
}
func NewUserService(repo UserRepository) *UserService {
return &UserService{repo: repo}
}
func (s *UserService) GetUserName(id int) (string, error) {
user, err := s.repo.GetUser(id)
if err != nil {
return "", err
}
if user == nil {
return "", errors.New("user not found")
}
return user.Name, nil
}
4.2 UserServiceのテスト実装
user_service_test.go
package example_test
import (
"errors"
"testing"
"github.com/golang/mock/gomock"
"example"
)
func TestGetUserName_Success(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockRepo := example.NewMockUserRepository(ctrl)
mockRepo.EXPECT().GetUser(1).Return(&example.User{ID: 1, Name: "John"}, nil)
service := example.NewUserService(mockRepo)
name, err := service.GetUserName(1)
if err != nil {
t.Fatal("expected no error, but got", err)
}
if name != "John" {
t.Fatal("expected name to be John, but got", name)
}
}
func TestGetUserName_NotFound(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockRepo := example.NewMockUserRepository(ctrl)
mockRepo.EXPECT().GetUser(1).Return(nil, nil)
service := example.NewUserService(mockRepo)
_, err := service.GetUserName(1)
if err == nil || err.Error() != "user not found" {
t.Fatal("expected user not found error, but got", err)
}
}
-
mockRepo.EXPECT()を使って、期待する動作を設定 - テストケースとして、成功ケースとユーザーが見つからないケースを実装
まとめ
| 項目 | 説明 |
|---|---|
| GoMock | Go言語用のモック生成ライブラリ |
| Mockgen | インターフェースからモックを自動生成 |
| Controller | モックの動作を設定・検証する |
GoMockを使うことで、外部依存を切り離してテストできるため、高品質なユニットテストを効率的に書くことが可能になります!
Discussion