昨年の2019年の6月頃触っていたgolangで素晴らしいモックの作成方法を学んだのに、
半年たってモックを作成しようとしたらテストの書き方含め「どうやるんだっけ...?」と忘れてしまいました。
エビングハウスの忘却曲線によると学んだことは1ヶ月後も経てばほぼ忘れてると同義らしいので、
忘れた事を悲観するのではなく、アウトプットを含めた復習をすることで記憶を強化したいと思います。
github.comのソースはこちら
サンプルプログラム
例えばこんなプログラムがあったとします。
layer1.go
package exPackage
type exStruct1 struct {
Layer2 Layer2Interface
}
type Layer1Interface interface {
Receiver() bool
}
func NewLayer1(Layer2 Layer2Interface) Layer1Interface {
return &exStruct1{Layer2}
}
func (e *exStruct1) Receiver() bool {
if e.Layer2.Get() != 1 {
return false
}
if e.Layer2.Put(2) == false {
return false
}
if e.Layer2.Delete(3) == false {
return false
}
return true
}
テストを書く時にNewLayer1メソッドに対して渡すLayer2はGet,Put,Deleteのメソッドを持つ事とします。
layer2.go
package exPackage
type Layer2Interface interface {
Get() int
Put(param int) bool
Delete(key int) bool
}
レイヤー2のモックを作成してテストをしたいのでモックを作成します。
Mockの作成
Get,Put,Deleteのメソッドの返却はすべてFake XXXX というメソッドに丸投げします。
package exMock
import "golang-public/test-benchMark/exMock/exPackage"
type Layer2 struct {
exPackage.Layer2Interface
FakeGet func() int
FakePut func(param int) bool
FakeDelete func(key int) bool
}
func (l Layer2) Get() int {
return l.FakeGet()
}
func (l Layer2) Put(param int) bool {
return l.FakePut(param)
}
func (l Layer2) Delete(key int) bool {
return l.FakeDelete(key)
}
テストの作成
こうすることで、素晴らしい事にモックの内容をテスト単位で書き換える事が可能になる。
func TestReceiver(t *testing.T) {
tests := []struct {
name string
f func(*testing.T)
}{
{
"Getでfalseが返却される",
func(t *testing.T) {
layer2Mock := exMock.Layer2{
FakeGet: func() int {
return 2
},
}
layer1 := exPackage.NewLayer1(layer2Mock)
assert.Equal(t, layer1.Receiver(), false)
},
},
{
"Putでfalseが返却される",
func(t *testing.T) {
layer2Mock := exMock.Layer2{
FakeGet: func() int {
return 1
},
FakePut: func(param int) bool {
return false
},
}
layer1 := exPackage.NewLayer1(layer2Mock)
assert.Equal(t, layer1.Receiver(), false)
},
},
{
"Deleteでfalseが返却される",
func(t *testing.T) {
layer2Mock := exMock.Layer2{
FakeGet: func() int {
return 1
},
FakePut: func(param int) bool {
return true
},
FakeDelete: func(key int) bool {
return false
},
}
layer1 := exPackage.NewLayer1(layer2Mock)
assert.Equal(t, layer1.Receiver(), false)
},
},
{
"すべてが成功してtrueが返却される",
func(t *testing.T) {
layer2Mock := exMock.Layer2{
FakeGet: func() int {
return 1
},
FakePut: func(param int) bool {
return true
},
FakeDelete: func(key int) bool {
return true
},
}
layer1 := exPackage.NewLayer1(layer2Mock)
assert.Equal(t, layer1.Receiver(), true)
},
},
}
for _, tt := range tests {
t.Run(tt.name, tt.f)
}
}