2016-04-18 16 views
0

私は(テストパッケージを使用して)私のコードのためのいくつかのテストを開発しています、と私はテスト関数の内部機能を模擬するための最良の方法です何を疑問に思って:Golangテストモック機能のベストプラクティス

は私が渡す必要がありますパラメータとしての機能? その場合、その関数が別の関数を呼び出すとどうなりますか?最初の関数と2番目の関数の両方をテスト済みのパラメータとして渡す必要がありますか?

注:関数のいくつかはオブジェクト(someObj.Create())で呼び出され、HTTP API呼び出しを使用します。明確化のため

UPDATE:

例:機能上記の場合

func f1() error { 
    ... //some API call 
} 

func (s *SomeStruct) f2() error { 
    return f1 
} 

func f3() error { 
    return nil 
} 

func f4() error { 
    ... 
    err = obj.f2() 
    ... 
    err = f3() 
    ... 
} 

:私はF4をテストしたい場合は、F2及びF3を模擬するための最良の方法は何ですか?

パラメータとしてf2とf3を渡すと、それはうまくいくはずですが、f2テストではどうなりますか?パラメータとしてf1をf2に渡すべきですか?

もしそれならば、f4はf1もパラメータに含めるべきですか?

+0

のテストについての詳細を学ぶことができますテストされた関数の中で、正確にはどういう意味ですか? – AJPennster

+0

質問を例で更新しました。私はそれがより明確であることを望む。私は非常にテストに新しいですし、私は100%もどのように依頼することではない – Ciack404

+0

あなたはもっと明確にする必要があります。これらの機能は、あなたがテストしているパッケージにありますか? – AJPennster

答えて

3

一般的なガイドラインとして、関数は非常に嘲笑的ではないので、異なるコードブランチをテストするための関数に渡すことができる特定のインターフェイスを実装する模擬構造体への最大の関心事です。基本的な例については以下を参照してください。上記の例では

package a 

type DoSomethingInterface interface { 
    DoSomething() error 
} 


func DoSomething(a DoSomethingInterface) { 
    if err := a.DoSomething(); err != nil { 
     fmt.Println("error occurred") 
     return 
    } 
    fmt.Println("no error occurred") 
    return 
} 

package a_test 

import (
    "testing" 
    "<path to a>/a" 
) 

type simpleMock struct { 
    err error 
} 

func (m *simpleMock) DoSomething() error { 
    return m.err 
} 

func TestDoSomething(t *testing.T) { 
    errorMock := &simpleMock{errors.New("some error")} 
    a.DoSomething(errorMock) 
    // test that "an error occurred" is logged 

    regularMock := &simpleMock{} 
    a.DoSomething(regularMock) 
    // test "no error occurred" is logged 
} 

、あなたは例えば起こるDoSomething機能や枝をテストします。 1つのテストケースに対してエラーのモックのインスタンスを作成し、エラーのないモックの別のインスタンスを作成して、他のケースをテストします。それぞれのケースは、特定の文字列をテストすることが標準出力に記録されています。この場合、simpleMockがエラーでインスタンス化され、がエラーでインスタンス化されていない場合は"no error occurred"となると、"error occurred"になります。

もちろんこれは他のケースにも拡張できます。 DoSomething関数は実際に何らかの値を返し、その値にassertionを作りたいとします。

編集:

私は、インターフェイスが別のパッケージに住んでいることを懸念して、コードを更新しました。新しい更新されたコードには、インターフェイスとテスト対象の関数を含むaパッケージと、a.DoSomethingのテスト方法のテンプレートであるパッケージa_testがあります。

+0

こんにちは、問題は、私が使用する必要のあるインタフェースが、テストする必要がある同じパッケージにないということです。別のパッケージにインターフェイスを実装することは可能ですか?私は探していますが、例を見つけることができません – Ciack404

+0

はい、別のパッケージに別のインターフェイスを実装することはできます。 Goは、インタフェースに従うために明示的な「実装」を必要としない代わりに、実際には動的言語でのダックタイピングというよりも、Javaとは異なります。あなたがしなければならないのは、特定の構造体に対して同じメソッドを持ち、構造体が、その関数が期待するインタフェースを満たすために使用できることだけです。 –

+0

@ Ciack404私は興味のあるかもしれないインターフェイスコードをテンプレートにコードサンプルを更新しました。それが役に立ったら教えてください。 –

0

私はあなたがここで何をしようとしているのかよく分かりませんが、Goでテストを行う方法について説明します。

root/ 
    pack1/ 
    pack1.go 
    pack1_test.go 
    pack2/ 
    pack2.go 
    pack2_test.go 
    main.go 
    main_test.go 

我々はpack2.goはあなたがテストしたい機能を持っていると仮定します:

package pack2 

func f1() error { 
    ... //some API call 
} 

func (s *SomeStruct) f2() error { 
    return f1 
} 

func f3() error { 
    return nil 
} 

func f4() error { 
    ... 
    err = obj.f2() 
    ... 
    err = f3() 
    ... 
} 

は、これまでのところ良いルックス

は、我々は、以下のディレクトリ階層を使用してアプリケーションを考えてみましょう。pack2の関数をテストする場合は、pack2_test.goというファイルを作成します。 goのすべてのテストファイルには、同様の名前(packagename_test.go)が付けられています。パッケージの典型的なテスト(この例ではpack2_test.go)の内部を見ることができます:

私は説明しましょう。 pack2_test.goの最初の行で、パッケージがpack2であることがわかります。つまり、パッケージpack2の "スコープ"に入っているので、pack2のようにpack2にあるすべての関数を呼び出すことができます。それで、Testf *関数の中で、関数をpack2から呼び出すことができたのはなぜですか?注意すべきもう一つは、インポートされたパッケージ "testing"です。これは次の2つの点で役に立ちます。

まず、テストを実行するための機能をいくつか提供します。私はそれに行きません。 第2に、go testが実行すべき機能を特定するのに役立ちます。

今機能に。テストパッケージ内の接頭辞「Test」とパラメータ「t * testing.T」(テスト機能を使用する必要がない場合は「* testing.T」を使用できます)を持つ関数は、実行go test。前述のテスト機能を参照するには、変数tを使用します。接頭辞なしで関数を宣言し、接頭辞付き関数内で呼び出すこともできます。

私は自分の端末に移動してgo testを実行するのであれば、それはpack2_test.go

に指定され、テストしたい機能を実行しますあなたはモック関数を言うときherehere

+0

こんにちは、返信ありがとうございます。しかし、package2の関数がpackage1の関数(インターフェース)を使って私が模倣する必要がある場合はどうなりますか?私があなたの例で正しいとすれば、同じパッケージ内のすべての関数をテストしますが、正しいのでしょうか? – Ciack404

+0

pack1から関数を呼び出す必要がありますか?これを行う: ' import pack1; pack1.Function()//関数を呼び出します 関数は大文字で始まりますが、publicにする必要があります。 – AJPennster

関連する問題