🛫

GoMock入門:初心者向けの使い方とテストの書き方

2025/02/27に公開

はじめに

GoMockは、Go言語でモック(Mock)を使ったテストを簡単に書けるようにするライブラリです。
外部APIやデータベースに依存するコードをテストする際、GoMockを使うことで依存関係を分離し、効率的なユニットテストが実現できます。

本記事では、GoMockの基本的な使い方を中心に、以下の内容を解説します。

対象読者

  • Go言語のテストを学び始めた方
  • 外部APIやDBに依存しないテストを書きたい方
  • GoMockを使ってモックを作成したい方

目次

  1. GoMockとは?
  2. インストール方法
  3. 基本的な使い方
    • モックの生成
    • モックの設定
    • モックの検証
  4. 実践: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を使って、外部依存を分離したユニットテストを実装します。
今回は、UserServiceUserRepositoryに依存しているケースをテストします。

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