2015-09-12 4 views
1

У меня есть следующие классы:ошибка шины GMock в деструкторе

class D1; 
class D2; 
class Base 
{ 
Public: 
    Base(); 
    virtual ~Base() { if (instance) delete instance; } 
    static Base* GetInstance(); 

    virtual int Get() = 0; 
    virtual int Set(const int val) = 0; 
private: 
    static Base* instance; 
}; 

Base *Base::instance = nullptr; 

Base* Base::GetInstance() 
{ 
    if (some_condition) 
    return new D1; 
    else 
    return new D2; 
} 

class D1 : public Base 
{ 
public: 
... 
    virtual int myD1Method() 
    { 
     ... 
    } 
    int Get() 
    { 
    ... 
    } 
    int Set(const int val) 
    { 
    ... 
    } 
private: 
// members... 
}; 

class D2 : public Base 
{ 
public: 
... 
    int Get() 
    { 
    ... 
    } 
    int Set(const int val) 
    { 
    ... 
    } 
private: 
// members... 
}; 

Чтобы проверить мой класс D1, я создал макет класса с помощью Google макет структуры, как это:

class MockD1 : public D1 
{ 
protected: 
    using D1::MyD1Method; 

    MockD1() : base(Base::GetInstance()) {} 

    MOCK_METHOD0(MyD1Method, int()) 

private: 
    Base *base; 
}; 

TEST(MockTest, TestD1) 
{ 
    MockD1 md1; 

    EXPECT_CALL(md1, MyD1Method()).WillRepeatedly(Return(10)); 

    EXPECT_EQ(md1.Set(10), NO_ERROR); 
    EXPECT_EQ(md1.Get(), 10); 
} 

Испытание, кажется, работа хорошо. Тем не менее, я получаю сообщение об ошибке шины в конце теста. Когда я перехожу в gdb, он выглядит так, как будто он застрял в цикле в деструкторе базового класса и в итоге приводит к ошибке шины. Буду признателен за любые материалы о том, что я делаю неправильно. Заранее спасибо.

ответ

1

Проблема с этим деструктора:

virtual ~Base() { if (instance) delete instance; } 

И это не имеет ничего общего с GMock.

delete instance звонит Base::~Base() - и Base::~Base() звонки delete instance - это бесконечный цикл, который вы наблюдаете.

Правильное решение - не использовать одиночные игры. Вместо этого у вас может быть какая-то фабрика.

Вы можете также попытаться свести к нулю экземпляра перед удалением - что должно работать - но все равно - это не хороший дизайн, что каждый экземпляр базы является владельцем базы :: экземпляра (то есть контролировать свою жизнь):

virtual ~Base() 
{ 
    Base* instanceToDelete = instance; 
    instance = nullptr; 
    if (instanceToDelete) delete instanceToDelete; 
} 
+0

Спасибо. Я постараюсь использовать завод. –

Смежные вопросы