Featured image of post GoでSQLのユニットテストを書く(go-sqlmock)

GoでSQLのユニットテストを書く(go-sqlmock)

GoでDBをモックしたテストを書きたかった(n番煎じ)

まとめ

GoSQLのテストを書くときはgo-sqlmockを使うとデータベースのモックがかんたんに作れる.

環境

  • macOS Big Sur 11.2.3
  • go version go1.15.5 darwin/amd64
  • go-sqlmock v1.5.0

やりかた

こんな感じでDB(MySQL)のテーブル操作(CRUD)を行う関数について, ユニットテストを書きたくなった.

テスト用のDBを立てて実際に操作しても良いんだけど,
CIするときに面倒だったりするのでできればGoだけでDBをモックして完結したテストを書きたい.

こんなときにはgo-sqlmockが使える.

公式README1を参考にしながら関数Create()についてテストを書いてみるとこんな感じ.

ArrangeでDBのモックを作成し, 想定される引数に対する挙動を設定している.
エラーの有無や返す値の内容などもmock.Expect~().With~().With~()2で細かく設定できる.

同様にRead(), Update(), Delete()についても書いていく.
最終的なテストコードはこんな感じ.

最後にテストを実行してみる.

$ tree .
.
├── go.mod
├── go.sum
├── main.go
└── main_test.go

# テスト実行
$ go test -v ./...
=== RUN   TestCreate
=== RUN   TestCreate/Createが成功するケース
=== RUN   TestCreate/Createが失敗するケース
--- PASS: TestCreate (0.00s)
    --- PASS: TestCreate/Createが成功するケース (0.00s)
    --- PASS: TestCreate/Createが失敗するケース (0.00s)
=== RUN   TestRead
=== RUN   TestRead/Readが成功するケース
=== RUN   TestRead/Readが失敗するケース(QueryRowでエラー)
=== RUN   TestRead/Readが失敗するケース(Scanでエラー)
--- PASS: TestRead (0.00s)
    --- PASS: TestRead/Readが成功するケース (0.00s)
    --- PASS: TestRead/Readが失敗するケース(QueryRowでエラー) (0.00s)
    --- PASS: TestRead/Readが失敗するケース(Scanでエラー) (0.00s)
=== RUN   TestUpdate
=== RUN   TestUpdate/Updateが成功するケース
=== RUN   TestUpdate/Updateが失敗するケース
--- PASS: TestUpdate (0.00s)
    --- PASS: TestUpdate/Updateが成功するケース (0.00s)
    --- PASS: TestUpdate/Updateが失敗するケース (0.00s)
=== RUN   TestDelete
=== RUN   TestDelete/Deleteが成功するケース
=== RUN   TestDelete/Deleteが失敗するケース
--- PASS: TestDelete (0.00s)
    --- PASS: TestDelete/Deleteが成功するケース (0.00s)
    --- PASS: TestDelete/Deleteが失敗するケース (0.00s)
PASS
ok  	github.com/uzimihsr/golang-db-test	0.170s

できた.

おわり

go-sqlmockを使うことで, テスト用のDBを立ち上げることなくGoSQLのテストができた. べんり.

おまけ

ブラッシング後に必死に毛づくろいするねこ