🐼
【Go】~ モック化を意識してコードを書く ~
はじめに
お疲れ様です。
テストコードを書きたい!
と思い、DBをモック化してみようとしたところ、手が動かないという現象が起こりました。おそらく、テストの書きやすいコードを作るところから復習する必要があったので、改めて丁寧に考えます。
この記事で書くこと
- テストの書きにくいコード(構造体依存)
- 改善コード(
interface依存)
やりたいこと
- 実際のDBからモックDBへ切り替えてテストしやすくする
-
ポイント:
- 依存先が構造体だと差し替えができない
- 依存先がinterfaceだと差し替えができる
実践
ここではSay()関数をテストすることを考えます。
構造体依存
まず何も意識していないコードを書きます。
ここではSay()が構造体Studentに依存しています。
図にするとこんな感じ

package main
import "fmt"
type Student struct {
Name string
}
func (s *Student) Greet() string {
return "hello, " + s.Name
}
// この関数をテストしたい
func Say(s Student) string {
return s.Greet() + "!"
}
ここでもしSay()をテストしたいとします。
ただ、構造体Studentではなく、モック用のMockStudentを使用するとします。
このとき、この構造体依存だと困ります。
(Say()の引数はStudent型だからどうしよう...)
interface依存
ここでは、Say()関数はinterfaceのみに依存しています。
interfaceのメソッドを使用するので、その先の構造体が本番のものか、モック用なのか、は気にしません。
図にするとこんな感じ

package main
import "fmt"
type Person interface {
Greet() string
}
// 本番用
type Student struct {
Name string
}
func (s Student) Greet() string {
return "hello, " + s.Name
}
// テスト用のモック
type MockStudent struct {
Name string
}
func (m MockStudent) Greet() string {
return "hello world, " + m.Name
}
func Say(p Person) string {
return p.Greet() + "!"
}
テストするとき
func TestSay(t *testing.T) {
mock := MockStudent{"mock"}
output := Say(mock)
expected := "hello world, mock!"
if output != expected {
t.Errorf("output %q, expected %q", output, expected)
}
}
最後に
今回はDBをモック化する最初の考え方をたどりました。
今後は実際にDBをモックで置き換えてテストしてみます。
最後まで読んでいただきありがとうございました!
参考文献
Discussion