Думаю, у вас есть несколько вариантов. Как вы говорите, одним из вариантов является создание интерфейсов. Скажем, у вас есть классы
class Engine:
{
public:
void start(){ };
};
class Car
{
public:
void start()
{
// do car specific stuff
e_.start();
private:
Engine e;
};
Чтобы ввести интерфейсы - вам нужно сменить автомобиль, чтобы взять двигатель
class Car
{
public:
Car(Engine* engine) :
e_(engine)
{}
void start()
{
// do car specific stuff
e_->start();
private:
Engine *e_;
};
Если у вас есть только один тип двигателя - вы внезапно усложнили использование объектов Car (кто создает двигатели, кто владеет двигателями). В автомобилях много деталей, поэтому эта проблема будет продолжать расти.
Если вам нужны отдельные реализации, другой способ будет с шаблонами. Это устраняет необходимость в интерфейсах.
class Car<type EngineType = Engine>
{
public:
void start()
{
// do car specific stuff
e_.start();
private:
EngineType e;
};
В своих издевательствах вы могли бы создавать Автомобили со специализированными двигателями:
Car<MockEngine> testEngine;
Другой, другой подход, заключается в добавлении методов в Engine для проверки его, что-то вроде:
class Engine:
{
public:
void start();
bool hasStarted() const;
};
Затем вы можете добавить метод проверки в Car или наследовать от Car для проверки.
class TestCar : public Car
{
public:
bool hasEngineStarted() { return e_.hasStarted(); }
};
Для этого потребуется изменить Двигатель с частного на защищенный в классе Car.
В зависимости от ситуации в реальном мире, будет зависеть, какое решение лучше. Кроме того, у каждого разработчика будет своя святая Грааль того, как, по их мнению, код должен тестироваться модульно. Мои личные взгляды - помнить клиента / клиента. Предположим, что ваши клиенты (возможно, другие разработчики в вашей команде) будут создавать автомобили и не заботятся о двигателях. Поэтому я не хотел бы раскрывать понятия Engines (внутренний класс для моей библиотеки) просто для того, чтобы можно было выполнить модульное тестирование. Я бы предпочел не создавать интерфейсы и тестировать два класса вместе (третий вариант, который я дал).