...
どのように正確に、あなたはそれを嘲笑しましたか?
...しかし、亀のオブジェクトがローカルに作成されたときにどのように私は(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
}
がなぜむしろ画家のためのテストを通してよりも、明示的にdoSomethingのタートルクラスをテストしていません? –
DrawSomethingメソッドにはより多くの指示があります。私は、move()、turn()、penDown()などのようなタートルのメソッドを使用せずに矩形を描きたいので、DrawSomethingが呼び出されたときに正しく呼び出されるかどうかテストします。 – mcjay
さて、モッククラスはインターフェイスを介して通信する必要があります。 'void Painter :: DrawSomething()'に渡されるか、または 'Painter'によって参照メンバ変数として保持される' ITurtle'インタフェース(抽象クラス)を導入するべきです。 –