ho preso in giro la classe della tartaruga ...
Come esattamente hai fatto beffe di esso?
... ma come faccio a testare doSomething()
metodo (per esempio con EXPECT_CALL
) quando si crea l'oggetto della tartaruga a livello locale? È possibile senza modificare la classe Painter?
(sottolineatura mia)
La risposta semplice è: No.
Non è possibile iniettare magicamente una simulazione anziché una istanza reale utilizzata in un'altra classe senza disaccoppiarsi tramite un'interfaccia.
si dovrebbe avere qualcosa di simile al seguente codice invece:
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);
};
Fornire il vero implementazione per le dichiarazioni di cui sopra in una Tra separata unità nazionale.
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);
// ...
}
È possibile in alternativa, passare l'interfaccia ITurtle
alla funzione DrawSomething()
:
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
}
Perché non prova doSomething e la classe della tartaruga in modo esplicito, piuttosto che attraverso test per Painter ? –
Il metodo DrawSomething ha più istruzioni, voglio disegnare un rettangolo usando pochi metodi di tartaruga per esempio move(), turn(), penDown() ecc. E voglio test se sono chiamati correttamente quando viene chiamato DrawSomething. – mcjay
Bene, le classi di sdegno devono comunicare tramite interfacce. Dovresti introdurre un'interfaccia 'ITurtle' (classe astratta), che viene passata a' void Painter :: DrawSomething() 'o tenuta da' Painter' come variabile membro di riferimento. –