Предположим, у меня есть классы
class Inner {
public:
void doSomething();
};
class Outer {
public:
Outer(Inner *inner); // Dependency injection.
void callInner();
};
. Правильное модульное тестирование говорит, что у меня должны быть тесты для Inner
. Затем у меня должны быть тесты для Outer
, которые используют не настоящий Inner
, а скорее MockInner
, чтобы я выполнял модульные тесты для функциональности, добавленной просто Внешний
вместо полного стека Внешний
/ Внутренний
.
Для этого Googletest , кажется, предлагает повернуть Внутренний
в чистый абстрактный класс (интерфейс), например:
// Introduced merely for the sake of unit-testing.
struct InnerInterface {
void doSomething() = 0;
};
// Used in production.
class Inner : public InnerInterface {
public:
/* override */ void doSomething();
};
// Used in unit-tests.
class MockInner : public InnerInterface {
public:
/* override */ void doSomething();
};
class Outer {
public:
Outer(Inner *inner); // Dependency injection.
void callInner();
};
Итак, в производственном коде я бы использовал Внешний (новый Внутренний)
; при тестировании Внешний (новый MockInner)
.
ОК. В теории это выглядит неплохо, но когда я начал использовать эту идею во всем коде, Я обнаружил, что создаю чистый абстрактный класс для каждого долбаного класса. Это много шаблонной типизации, даже если вы можете игнорировать небольшую производительность во время выполнения, которая может ухудшиться из-за ненужной виртуальной диспетчеризации.
Альтернативный подход - использовать шаблоны, как показано ниже:
class Inner {
public:
void doSomething();
};
class MockInner {
public:
void doSomething();
};
template
class Outer {
public:
Outer(I *inner);
void callInner();
};
// In production, use
Outer obj;
// In test, use
Outer test_obj;
Это позволяет избежать котла -облицовка и ненужная виртуальная рассылка; но теперь вся моя кодовая база находится в дурацких файлах заголовков, что делает невозможным скрытие исходных реализаций (не говоря уже о том, что нужно иметь дело с неприятными ошибками компиляции шаблонов и долгим временем сборки).
Эти два метода, виртуальные и шаблоны, являются только способы провести правильное модульное тестирование? Есть ли более эффективные способы проведения надлежащего модульного тестирования?
Под надлежащим модульным тестированием я подразумеваю , что каждый модульный тест проверяет только функции, представленные этим модулем, но не сам модуль » s также .