🐼

【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をモックで置き換えてテストしてみます。

最後まで読んでいただきありがとうございました!

参考文献

https://www.kadokawa.co.jp/product/322405000561/

Discussion