web-dev-qa-db-ja.com

golangのパッケージからインポートされた関数をモックすることは可能ですか?

パッケージからインポートされた関数を使用する、次のテスト方法があります。

_import x.y.z

func abc() {
    ...
    v := z.SomeFunc()
    ... 
}
_

GolangでSomeFunc()をモックすることは可能ですか?

26
Pradeep

はい、単純なリファクタリングで。 _z.SomeFunc_で初期化された関数タイプのzSomeFunc変数を作成し、z.SomeFunc()の代わりにそれを呼び出すパッケージを作成します。

_var zSomeFunc = z.SomeFunc

func abc() {
    // ...
    v := zSomeFunc()
    // ...
}
_

テストでは、別の関数をzSomeFuncに割り当てることができます。これは、テストで定義されており、テストが望んでいることは何でも行います。

例えば:

_func TestAbc(t *testing.T) {
    // Save current function and restore at the end:
    old := zSomeFunc
    defer func() { zSomeFunc = old }()

    zSomeFunc = func() int {
        // This will be called, do whatever you want to,
        // return whatever you want to
        return 1
    }

    // Call the tested function
    abc()

    // Check expected behavior
}
_

関連/可能な重複を参照してください: カバレッジ情報を使用したGoでのos.Exitシナリオのテスト(coveralls.io/Goveralls)

36
icza

あなたができることの一つはこれです:

import "x/y/z"

var someFunc = z.SomeFunc

func abc() {
    ...
    v := someFunc()
    ... 
}

そして、あなたのテストファイルでこれを行います。

func Test_abc() {
    someFunc = mockFunc
    abc()
}

ただし、これを同時に行うことを確認してください。TestXxxを呼び出すabc関数が複数ある場合、またはsomeFuncを設定する場合は、structsomeFuncフィールドとともに使用した方がよい場合があります。

8
mkopriva

関数ポインタとモンキーパッチを持っていることはそれを行うことの1つです。しかし、複数の関数をモックするときは、数の関数ポインターがあり、不必要に関数ポインターのみを使用して関数を呼び出す必要があります。

インターフェースを持ち、インターフェースを実装する構造体の一部を関数にすることをお勧めします。それが完了したら、Goで使用可能ないくつかのNiceツールを使用してモックを生成できます。

私はこれを使用しています:

mockgen -source myModule.go -package myPackage -destination myModuleMock.go

次の方法でインストールできます。

got get github.com/golang/mock
4