sqlxのmockの書き方のメモ書きです。
前提
次のようにsqlxのmockを生成していおくこと
import (
"github.com/DATA-DOG/go-sqlmock"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
func NewDB() (*sqlx.DB, sqlmock.Sqlmock, error) {
driver, mock, err := sqlmock.New()
if err != nil {
return nil, nil, err
}
db := sqlx.NewDb(driver, "sqlmock")
return db, mock, db.Ping()
}
func(t *testing.T) {
conn, mock, _ := test.NewDB() // sqlxのmockを生成
defer conn.Close()
# 以下にテストコード、mockを書く
}
Begin, Commitのモック
func内で次のように定義します。
mock.ExpectBegin()
mock.ExpectCommit()
SQL実行モック
PrepareNamed()
、PrepareNamedContext()
などでSQLを解析したあと、
ExecContext()
、SelectContext()
などでSQLを実行する際のmockは次のように定義します。
// selectの場合
// sqlを正しく定義
sql: = "SELECT age FROM test_table WHERE id = ?;"
// paramを正しく定義
param = []driver.Value{1}
// SELECTのカラム名とその値の期待値を設定
rowData := sqlmock.NewRows([]string{"age"}).AddRow(15)
// 下記のようにモックを定義する
mock.ExpectPrepare(regexp.QuoteMeta(sql)).ExpectQuery().WithArgs(param...).WillReturnRows(rowData)
// select以外
// sqlを正しく定義
sql: = "UPDATE test_table SET age = 14 WHERE id = ?;"
// paramを正しく定義
param = []driver.Value{1}
// WillReturnResultを定義し、sqlmock.NewResult()でInsertIDと変更する想定のカラム数を設定
mock.ExpectPrepare(regexp.QuoteMeta(sql)).ExpectExec().WithArgs(param...).WillReturnResult(sqlmock.NewResult(1, 1))
PrepareNamedのエラーモック
PrepareNamed()
、PrepareNamedContext()
のmockは次のように定義します。
// int型のidに文字列XXXを設定する
sql: = "UPDATE test_table SET age = 14 WHERE id = XXX;"
param = []driver.Value{1}
// WillReturnErrorを定義しエラー文を渡す
mock.ExpectPrepare(regexp.QuoteMeta(sql)).ExpectQuery().WithArgs(param...).WillReturnError(fmt.Errorf("PrepareNamedで失敗しました:"))
SQL実行部分のエラーモック
ExecContext()
、SelectContext()
などのmockは次のように定義します。
// sqlを正しく定義
sql: = "UPDATE test_table SET age = 14 WHERE id = ?;"
// paramを正しく定義
param = []driver.Value{1}
// PrepareNamedのモック同様、WillReturnErrorを定義しエラー文を渡す
mock.ExpectPrepare(regexp.QuoteMeta(sql)).ExpectQuery().WithArgs(param...).WillReturnError(fmt.Errorf("SQL実行で失敗しました:"))
RowsAffectedのエラーモック
WillReturnResultにsqlmock.NewErrorResult()を設定することができます。
// sqlを正しく定義
sql: = "UPDATE test_table SET age = 14 WHERE id = ?;"
// paramを正しく定義
param = []driver.Value{1}
// WillReturnResultにsqlmock.NewErrorResult()を設定
mock.ExpectPrepare(regexp.QuoteMeta(sql)).ExpectExec().WithArgs(param...).WillReturnResult(sqlmock.NewErrorResult(errors.New("RowsAffectedエラー")))