#googletest #googlemock
Вопрос:
Рассмотрим базовый класс B и два наследующих класса D1 и D2. B имеет общедоступную функцию под названием «запуск», которая вызывает чисто виртуальную функцию «запуск» при условии, возвращаемом функцией «someCondition». Запуск функции реализован классами D1 и D2, каждый класс использует собственную логику, представленную функциями «d1Condition» и «d2Condition».
Пример кода:
class B {
public:
virtual ~B() {}
void start() { if (someCondition()) run(); }
virtual bool someCondition() { return true; }
protected:
virtual void run() = 0;
};
class D1 : public B {
public:
D1();
virtual ~D1() {}
virtual bool d1Condition() { return true; }
protected:
virtual void run() {
if (d1Condition()) {
//some code
}
}
};
class D2 : public B {
public:
D2();
virtual ~D2() {}
virtual bool d2Condition() { return true; }
protected:
virtual void run() {
if (d2Condition()) {
//some code
}
}
};
Я хотел бы написать модульный тест для сценария «запуск» для классов D1 и D2. Я могу написать макет класса для D1 и еще один для D2. Фиктивный класс для D1 будет иметь фиктивную функцию для условия d1, а фиктивный класс для D2 будет иметь фиктивную функцию для функции D2. Тем не менее, чтобы запустить сценарий, мне нужна другая функция макета для некоторого условия(). Этот фиктивный метод будет действовать одинаково для обоих тестов D1 и D2 — он должен возвращать значение true, чтобы была вызвана функция run.
Как мне избежать избыточности фиктивного метода для некоторых условий ?
Ответ №1:
Для меня вы реализовали шаблон стратегии. И D1, и D2 решают одну и ту же проблему, используя разные подходы. Просто создайте чистый виртуальный защищенный метод, вызываемый runCondition
в базовом классе:
class B {
public:
virtual ~B() = defau<
void start() { if (someCondition()) run(); }
virtual bool someCondition() { return true; }
protected:
void run() {
if(runCondition()) {
// some code
}
}
// each derived class needs to implement this step in a different way
virtual bool runCondition() = 0;
};
Отсюда у вас есть 3 вещи, которые нужно проверить: класс B непосредственно, чтобы проверить это runCondition
и run
вызывается, когда start
вызывается (например, с помощью частичного насмешки — вы можете создать PartialBMock
, где someCondition
и runCondition
над кем будут насмехаться, и проверить, что происходит, когда start
вызывается). Тогда вам нужно будет протестировать D1
и D2
их runCondition
: т. е. посмотреть, при каких условиях run
будут вызываться. Если эти runCondition
реализации s трудно проверить — извлеките их в отдельные классы и используйте насмешки D1
и D2
тесты.