2017-01-28 4 views
1

Вопрос:Лучше MOCKing?

Предположим, у меня есть система классов, в которой есть часть компонента внутри. Чтобы правильно протестировать систему, мне нужно сохранить указатель на Component в классе System и разработать компонент для интерфейса IComponent с виртуальными методами. Затем в тесте я могу создать макет IComponent и передать его системе.

Но в некоторых ситуациях я не хочу такого подхода.

Существует другой способ использования шаблонов и указав компонент в качестве параметра шаблона, например:

template <class Component> 
class System 
{ 
    // ... 
    Component _component; 
}; 

Тогда, в моем тесте я могу создать систему, придавая ему Mock компонентных, как это:

System<MockComponent> theSystem; 

The MockComponent не necesarrily наследоваться от IComponent, в моем подходе я не хочу IComponent, я просто хочу MockComponent иметь некоторые необходимые методы, так же, как в компоненте.

Но проблема с этим подходом заключается в том, что я хочу проинструктировать MockComponent, что делать, дать ему некоторые ожидания и сказать, что вернуть. Из теста у меня нет доступа к MockComponent, потому что он живет в Системе. Если в Системе появился компонент Component, это было бы нормально, но иногда я не хочу получать компонент Component в Системе. Затем, в тесте, мне нужно создать еще один класс, MockSystem и оснастить его получателем компонента (а также убедиться, что _компонент в исходной системе находится в разделе «protected»).

template <Class Component> 
MockSystem : public System 
{ 
public: 
    Component GetComponent() { return _component; } 
}; 

Затем в тесте я могу:

MockSystem<MockComponent> theSystem; 
MockComponent mockComponent = theSystem.GetComponent(); 
EXPECT_CALL(mockComponnent, ...); 

Этот подход работает отлично.

Но ... Интересно, есть ли способ немного упростить это.

Что делать, если у меня был механизм генерации во время компиляции класса MockSystem из класса System? Я хочу сказать, что хотел бы получить класс System с геттерами для всех параметров шаблона.

Я знаю, что шаблон метапрограммирования может творить чудеса, но я не эксперт в TPM. Я читал некоторые примеры и видел Boost :: Hana в действии, и задаюсь вопросом, если это выполнимо.

Неужели кто-нибудь из ребят здесь слышал или видел рамки для чего-то подобного? Или есть другой подход?

С уважением YK

ответ

0

Вы можете определить обертку над макетом класса - для обеспечения доступа к насмешке:

struct ComponentMock 
{ 
    MOCK_METHOD0(foo, int()); 
}; 
struct ComponentMockWrapper 
{ 
    static ComponentMock* mock; 
    int foo() 
    { 
     return mock->foo(); 
    } 
}; 
ComponentMock* ComponentMockWrapper::mock; 

Тогда, в вашем TestSuite:

class SystemTestSuite : public testing::Test 
{ 
protected: 
    ComponentMock componentMock; 
    void SetUp() override 
    { 
     ComponentMockWrapper::mock = &componentMock; 
    } 
    System<ComponentMockWrapper> objectUnderTest; 
}; 

И тест, как это :

TEST_F(SystemTestSuite1, shallFooComponent) 
{ 
    EXPECT_CALL(componentMock, foo()); 
    objectUnderTest.foo(); 
} 

Но быть в курсе таких проблем, как - что делать, если 2 или более Component необходимо, или как следить за время жизни проверяемой Component ...


Может быть, лучше было бы пожертвовать немного инкапсуляции в пользу проверяемости - то есть получить защищенный доступ к компоненту:

template <class Component> 
class System 
{ 
protected: 
    Component& getComponent(); // for UT only 
}; 

и позволяют доступ общественности в УТ, продвигая эту функцию:

template <class Component> 
class SystemTestable : public System<Component> 
{ 
public: 
    using System<Component>::getComponent; 
}; 

class SystemTestSuite : public testing::Test 
{ 
protected: 
    SystemTestable<ComponentMock> objectUnderTest; 
};