golang
unittest

go mockについての悩み(続#1)

前回こんなことを書いてみた。

go mockについての悩み

それに近いことをやろうとするとこうなるのかなと思った。

骨子は以下の通り。


  1. 本来の関数定義がされている場所の実装を少し変更する。具体的には、


    • モックする関数名を書き換える

    • 本来の関数名をグローバル変数として定義し、その先を上記1の 書き換えた関数名 にする



  2. テスト内では、グローバル変数を駆使して、モックしたい関数をうまいこと入れ替える

具体的には以下参照。


main.go

package main

import "fmt"

func main() {
// ReturnFalse() はすなわち return_false() と同じ
fmt.Println(ReturnFalse())
}


funcs.go

package main

var ReturnFalse = return_false

/*
もともと ReturnFalse という定義を、あえてグローバル変数に格上げして
その先の関数に(ここでは) return_false という関数をセットする
*/

func return_false() bool {
return false
}


funcs_test.go

package main

import (
"testing"
)

func TestFiveHoursAgo(t *testing.T) {
/*
事実上のモック箇所
ReturnFalse を別定義の無名関数で上書きする
*/

ReturnFalse = func() bool { return true }

ret := ReturnFalse()
exp := true

if exp != ret {
t.Errorf("actual %v\nwant %v", ret, exp)
}

// ここでもとに戻す。実際には defer 処理でやればいい
ReturnFalse = return_false
}

実行するとこうなる。

% go test funcs.go funcs_test.go

ok command-line-arguments 0.007s

ただ毎回こんなことをするのは無理があるので、実際には難しい気がする。

ということで調べていると、withmock が良さそうなんだけど、moduleモードではちゃんと動いてくれないな・・・。

withmock