🎉

【Go】gorm❌sql-mockの使い方

2022/08/30に公開

背景

バイトでmockのテストを書くときに使うことになったので、基本的なことを抑えるために記事にしました。

sql-mockとは

sql-mockとはデータベースを使うテストを実行するときに用いるものです。テストをする時に元々用意してあるデータベースを使ってテストをすることはない。そこで、テスト用のデータ(mock)を別に用意をして、データベースを扱うテストを行う。goであればsql-mockを用いることが多い。

テスト例

こちらのuserを作成するメソッドをテストしていきます。

controller.go
func Post(db *gorm.DB, name string, password string) *models.User {
	user := models.User{}
	var err error
	user.Name = name
	user.Password, err = handler.PasswordEncrypt(password)
	user.UUID = uuid.New().String()
	user.Created_at = time.Now()

	if err != nil {
		fmt.Println("パスワード暗号化中にエラーが発生しました。:", err)
	}

	db.Create(&user)
	return &user
}

次にテストで使うデータベースを作成します。

mock/db.go
package mock

import (
	"github.com/DATA-DOG/go-sqlmock"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

func GetNewDbMock() (*gorm.DB, sqlmock.Sqlmock, error) {
	db, mock, err := sqlmock.New()
	if err != nil {
		return nil, mock, err
	}
	
	gormDB, err := gorm.Open("mysql", db) //通常ならここにdbのurlが入るが、テストの場合はmockで作ったdbを入れる。
	if err != nil {
		return gormDB, mock, err
	}
	return gormDB, mock, err
}

次にテストを作成します。

controller_test.gpo
  func TestPost(t *testing.T) {
      db, mock, err := mock.GetNewDbMock()
      if err != nil {
          t.Errorf("Failed to initialize mock DB: %v", err)
          return
      }

      var id int = 1
      var name string = "user1"

      // Mock設定発酵されたクエリが正しいかどうかを確認す
      mock.ExpectBegin()
      mock.ExpectQuery(`INSERT INTO "users" (.+) RETURNING`).
          WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(id, name))
      mock.ExpectCommit()

      res, err := CreateTag(db, "user1")

      assert.Equal(t, *res.ID, id)
      assert.Equal(t, res.Name, name)
  }

ExpectBegin():処理を開始する関数
ExpectQuery:期待するSELECT文と取得結果の組み合わせをモック化します。
WillReturnRows:期待する取得結果に必要なカラムを指定します。
NewRows:返り値としてNewRows関数を指定します。
ExpectCommit:コミットを期待する関数

最後に

sql-mockを使ったのでまとめてみました。まだ、他にも使い方があるので、もう少し勉強します!

Discussion