2016-04-27 5 views
5

Я начал использовать библиотеки googletest и googlemock, и у меня есть проблема, которую я не могу решить. У меня есть код что-то вроде этого:C++, Googlemock - проверка локального объекта

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

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

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

я высмеивал класс черепахи, но как я могу проверить метод DoSomething() (например, с EXPECT_CALL), когда объект черепахи создается локально? Возможно ли это без изменения класса Painter?

Благодарим за ответы.

+0

Почему бы не проверить DoSomething и класс Черепаха в явном виде, а не с помощью тестов для Painter ? –

+0

Метод DrawSomething имеет больше инструкций, я хочу нарисовать прямоугольник, используя несколько методов черепахи, например move(), turn(), penDown() и т. Д., И я хочу проверить, правильно ли они вызываются при вызове DrawSomething. – mcjay

+0

Ну, насмешливые классы должны общаться через интерфейсы. Вы должны ввести интерфейс 'ITurtle' (абстрактный класс), который передается' void Painter :: DrawSomething() 'или удерживается' Painter' в качестве ссылочной переменной-члена. –

ответ

3

Я дразнил класс Черепаха ...

Как именно вы дразнить его?

... но как я могу проверить doSomething() метод (например, с EXPECT_CALL), когда объект черепахи создается локально? Возможно ли без модификации класса 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); 
}; 

Обеспечить реальной реализации вышеуказанных деклараций в отдельном прозрачны nslation.


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

Вы можете альтернативно пройти интерфейс ITurtle функции 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 

} 
+0

Большое спасибо за подробное объяснение, я издевался над черепахой точно так же, как и в классе TurtleMock.Только один вопрос: допустим, что у меня нет члена ITurtle в классе Painter, а объект Turtle создан только в функции DrawSomething. Если я хочу передать макет объекта этому методу, единственный способ сделать DrawSomething (ITurtle & turtle)? – mcjay

+1

@mcjay _ «единственный способ сделать« DrawSomething (ITurtle & turtle) »?» _ Да, это альтернатива. –