2017-06-14 6 views
0

私はFunctionalityClientTestClientの2つの構造体を持っています。どちらもInterfaceを実装しています。私はInterfaceタイプのグローバル変数Clientを持っています。 Clientには、実際のクライアントか模擬クライアントのどちらかが、テストか通常の実行かによって割り当てられます。構造体をGolangのメンバー関数で正しくモックする方法は?

Interfaceは、私がテストで嘲笑したい方法Requestを持っています。それは私がしたい、次のとおりです。

:引数が関数に渡された関数から
  • 復帰いくつかの任意に定義された戻り値
  • ので、構造体は、このように見えるか

    • 記録
      type TestClient struct { 
          recordedArgs []interface{} 
          returnValues []interface{} 
      } 
      func (c *TestClient) Request(body io.Reader, method string, endpoint string, headers []Header) ([]byte, error) { 
          c.recordedArgs = append(c.recordedArgs, []interface{}{body, method, endpoint, headers}) // this can't be typed if I want the code to be reusable 
           if len(c.returnValues) != 0 { 
           last := c.returnValues[0] 
           c.returnValues = c.returnValues[1:] 
           return last.([]byte), nil 
          } 
          return nil, nil 
      } 
      

      そして、私はそうのようにそれを使用します。

      testClient := TestClient{ 
          returnValues: []interface{}{ 
           []byte("arbitrarily defined return value"), 
           []byte("this will be returned after calling Request a second time"), 
          } 
      } 
      Client = &testClient 
      // run the test 
      // now let's check the results 
      r1 := testClient.recordedArgs[1].([]interface{}) // because I append untyped lists to recordedArgs 
      assert.Equal(t, "POST", r1[1].(string)) 
      assert.Equal(t, "/file", r1[2].(string)) 
      // and so on 
      

      今質問があります。

      私はこのような模擬したいいくつかの構造体を持っています。現在、私は各構造体の上記のコードをコピーして貼り付けています。しかし、それは本当にうんざりです、私はモックロジックを何らかの形で抽象化したいと思います。また、私はMockitoのwhenのようなものを受け入れます:特定の引数で模擬関数が呼び出されたときに、特定の値を返し、呼び出しを記録します。

      構造体をGolangのメンバー関数で正しくモックできますか?

    +0

    recordsArgsを[] [] interface {}にすると、すべての要素が[] interface {}になることがわかっているので、これをやや簡単にすることができます。それはあなたにいくつかの不必要な型アサーションを保存します。 – Adrian

    答えて

    0

    HTTP APIのクライアントを嘲笑している場合は、httptest.Serverを使用するだけで、これを大幅に簡素化できます。クライアントを嘲笑するのではなく、クライアントが接続するサーバーを模擬してください。これは本当に使い方が簡単で、リクエストメソッド、パス、ボディなどを記録したり、擬似クライアントと同じように任意のレスポンス値を返すことができます。

    それはオプションではない場合、あなたはそれを再利用可能にするためにあなたのモックメソッドアウト抽象することができます:

    type TestClient struct { 
        recordedArgs [][]interface{} 
        returnValues []interface{} 
    } 
    
    func (c *TestClient) mock(args ...interface{}) interface{} { 
        c.recordedArgs = append(c.recordedArgs, args) 
        if len(c.returnValues) != 0 { 
         last := c.returnValues[0] 
         c.returnValues = c.returnValues[1:] 
         return last 
        } 
        return nil 
    } 
    
    func (c *TestClient) Request(body io.Reader, method string, endpoint string, headers []Header) ([]byte, error) { 
        return c.mock(body,method,endpoint,headers).([]byte), nil 
    } 
    

    これは1行までのご利用状況に固有の方法をカットします。

    関連する問題