2016-04-27 2 views
5

私はgoogletestとgooglemockライブラリを使い始めました。私は解決できない問題があります。私はこのようなコードに何か持っている:私は亀のクラスを嘲笑しているC++、GoogleMock - ローカルオブジェクトのテスト

class Painter 
{ 
    public: 
    void DrawSomething(); 
}; 

void Painter::DrawSomething() 
{ 
    Turtle turtle; 
turtle.doSomething(); 
} 

main() 
{ 
    Painter p; 
    p.DrawSomething(); 
} 

のが、亀のオブジェクトがローカルに作成されたときにどのように私は(EXPECT_CALLでたとえば)のdoSomething()メソッドをテストすることができますか? Painterクラスを変更しなくても可能ですか?

ありがとうございました。

私はタートルクラスを嘲笑している
+0

がなぜむしろ画家のためのテストを通してよりも、明示的にdoSomethingのタートルクラスをテストしていません? –

+0

DrawSomethingメソッドにはより多くの指示があります。私は、move()、turn()、penDown()などのようなタートルのメソッドを使用せずに矩形を描きたいので、DrawSomethingが呼び出されたときに正しく呼び出されるかどうかテストします。 – mcjay

+0

さて、モッククラスはインターフェイスを介して通信する必要があります。 'void Painter :: DrawSomething()'に渡されるか、または 'Painter'によって参照メンバ変数として保持される' ITurtle'インタフェース(抽象クラ​​ス)を導入するべきです。 –

答えて

3

...

どのように正確に、あなたはそれを嘲笑しましたか?

...しかし、亀のオブジェクトがローカルに作成されたときにどのように私は(EXPECT_CALLで例えば)doSomething()メソッドをテストすることができますか? Painterクラスを変更しなくても可能ですか?
(重点鉱山)

簡単な答えは次のとおりです。ません

リアルインスタンスの代わりに、モックを魔法のように注入することはできません。別のクラスでは、インターフェイス経由でデカップリングすることなく使用されます。


かわりに、次のコードのようなものを持っている必要があります。

struct ITurtle { 
    virtual void PenUp() = 0; 
    virtual void PenDown() = 0; 
    virtual void TurnLeft(double degrees) = 0; 
    virtual void Move(double distance) = 0; 
    // ... 
    virtual ~ITurtle() {} 
}; 

struct TurtleMock : ITurtle { 
    // Mock method declarations 
    MOCK_METHOD0(PenUp, void()); 
    MOCK_METHOD0(PenDown, void()); 
    MOCK_METHOD1(TurnLeft, void (double)); 
    MOCK_METHOD1(Move, void (double)); 
}; 

class Turtle : public ITurtle { 
public: 
    void PenUp(); 
    void PenDown(); 
    void TurnLeft(double degrees); 
    void Move(double distance); 
}; 

は別々のTRAで上記の宣言のための本当実装を提供しますユニット。


class Painter { 
public: 
    Painter(ITurtle& turtle) : turtle_(turtle) {} 
    void DrawSomething(); 
private: 
    ITurtle& turtle_; 
}; 

void Painter::DrawSomething() { 
    turtle_.PenDown(); 
    turtle_.TurnLeft(30.0); 
    turtle_.Move(10.0); 
    turtle_.TurnLeft(30.0); 
    turtle_.Move(10.0); 
    // ... 
} 

あなたは、代わりDrawSomething()関数にITurtleインターフェースを渡すことができます。

class Painter { 
public: 
    void DrawSomething(ITurtle& turtle); 
}; 

void Painter::DrawSomething(ITurtle& turtle) { 
    turtle.PenDown(); 
    turtle.TurnLeft(30.0); 
    turtle.Move(10.0); 
    turtle.TurnLeft(30.0); 
    turtle.Move(10.0); 
    // ... 
} 

int main() { 
    NiceMock<TurtleMock> turtle; 
    Painter p(turtle); 
    // Painter p; <<< for the alternative solution 

    EXPECT_CALL(turtle,PenDown()) 
     .Times(1); 
    EXPECT_CALL(turtle,TurnLeft(_)) 
     .Times(2); 
    EXPECT_CALL(turtle,Move(_)) 
     .Times(2); 

    p.DrawSomething(); 
    // p.DrawSomething(turtle); <<< for the alternative solution 

} 
+0

詳細についてはありがとうございました。私はTurtleMockクラスで行ったのとまったく同じように亀を嘲笑しました。たった1つの質問だけです.PaintterクラスにITurtleメンバーがなく、TurtleオブジェクトがDrawSomething関数でのみ作成されたとします。モックオブジェクトをこのメソッドに渡したい場合は、DrawSomething(ITurtle&turtle)を作成するしかありません。 – mcjay

+1

@mcjay _ "唯一の方法は' DrawSomething(ITurtle&turtle) 'を作ることです?" "はい、そうです。 –

関連する問題