【Go言語のtest】interface を利用して mock を使う
概要
外部 API や DB が関わるコードのテストでモックを使いたい場面は多々あると思う。
interface を使って、テストでモックに切り替えることができるのでメモ。
インターフェイスを定義
type DB interface { Add(name string) error Delete(name string) error }
実際に使う実装(DynamoDB)
type Dynamo struct { DB *dynamodb.DynamoDB } // main 関数などからの呼び出し用のコンストラクタ func NewDynamo() (*Dynamo, error) { sess, err := session.NewSession() if err != nil { return nil, err } return &Dynamo{DB: dynamodb.New(sess)}, nil } func (d *Dynamo) Add(name string) error { // 追加の処理。d.DB.PutItem(input) } func (d *Dynamo) Delete(name string) error { // 削除の処理 }
main から呼び出す
type App struct { DB DB } func main() { db, err := NewDynamo() if err != nil { log.Fatal(err) } app := &App{ DB: db, } app.DB.Add("hoge") }
実行すると DynamoDB にデータ追加された
テストの実装
type mockDB struct { } func (m *mockDB) Add(name string) error { log.Println("=== mock add") return nil } func (m *mockDB) Delete(name string) error { return nil }
テストから呼び出す
func TestMain(t *testing.T) { app := &App{ DB: &mockDB{}, } app.DB.Add("hoge") }
テストを実行すると、DynamoDBにデータは追加されいない。
ログも出力され、モックのAddが実行されてる。
その他 Tips
インターフェース埋め込み
type mockDB struct { DB } func (m *mockDB) Add(name string) error { log.Println("=== mock add") return nil }
インターフェースを満たすために DB interface を埋め込むことができる。
func (m *mockDB) Delete(name string) error
を用意しなくて済む。