2016-04-27 25 views
5

Ich begann mit googletest und googlemock-Bibliotheken und habe ein Problem, das ich nicht lösen kann. Ich habe einen Code so etwas wie diese:C++, Goommemock - testet lokales Objekt

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

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

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

ich die Schildkröte Klasse verspottet habe, aber wie kann ich testen doSomething() -Methode (zum Beispiel mit EXPECT_CALL), wenn das Objekt der Schildkröte lokal erstellt wird? Ist es möglich, ohne Painter-Klasse zu ändern?

Vielen Dank für die Antworten.

+0

Warum nicht testen doSomething und die Schildkröte Klasse explizit, anstatt durch Tests für Maler ? –

+0

DrawSomething-Methode haben mehr Anweisungen, ich möchte ein Rechteck mit wenigen Turtle-Methoden wie move(), turn(), penDown() etc. und ich möchte testen, wenn sie richtig aufgerufen werden, wenn der DrawSomething aufgerufen wird. – mcjay

+0

Nun, Spott Klassen müssen über Schnittstellen kommunizieren. Sie sollten eine 'ITurtle'-Schnittstelle (abstrakte Klasse) einführen, die an' void Painter :: DrawSomething() 'übergeben oder von' Painter' als Referenzelementvariable gehalten wird. –

Antwort

3

ich die Schildkröte Klasse verspottet haben ...

Wie genau hast du es verspotten?

... aber wie kann ich doSomething() Verfahren (zum Beispiel mit EXPECT_CALL), wenn das Objekt der Schildkröte testen lokal erstellt? Ist es möglich ohne Painter-Klasse zu ändern?
(Hervorhebung von mir)

Die einfache Antwort lautet: Nein .

Sie können statt einer realen Instanz, die in einer anderen Klasse ohne Entkopplung über eine Schnittstelle verwendet wird, keinen Mock injizieren.


Sie sollten stattdessen so etwas wie den folgenden Code haben:

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); 
}; 

die echte Implementierung für die obigen Erklärungen in einem separaten tra Stellen Nslationseinheit.


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); 
    // ... 
} 

können Sie alternativ passieren die ITurtle Schnittstelle zur DrawSomething() Funktion:

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

Vielen Dank für die ausführliche Erklärung, ich verspottete die Schildkröte genau wie du es in TurtleMock Klasse getan hast.Nur eine Frage mehr: Sagen wir, ich habe kein ITurtle-Mitglied in der Painter-Klasse und Turtle-Objekt wird nur in DrawSomething-Funktion erstellt. Wenn ich das Mock-Objekt an diese Methode übergeben möchte, besteht die einzige Möglichkeit darin, DrawSomething (ITurtle & turtle) zu erstellen. – mcjay

+1

@mcjay _ "Der einzige Weg ist' DrawSomething (ITurtle & turtle) ''? "_ Ja, das ist die Alternative. –