Во-первых, это плохой дизайн, имеющий delete ptr_b;
в деструкторе класса A, поскольку в конструкторе A. нет new B()
. Это означает, что каждый раз, когда создается экземпляр A, вы передаете право собственности наB возражает против A, оставляя вас с потенциальным риском дубликата delete
для человека, использующего A, который не знает внутренностей.
Во-вторых, если вы хотите дать A "заглушку" (или "макет"", или" фальшивый ") объект вместо" реального B ", B
и FakeB
нужен общий интерфейс, содержащий все методы из B, которые нужны A как виртуальные методы:
class FakeB : public InterfaceB
и
class B : public InterfaceB
, поэтому все функции-члены A могут использовать параметры типа InterfaceB *
вместо B *
.Тогда внедрение объекта FakeB
в A
становится очевидным делом.
К сожалению, это означает, что вам нужно изменить B (по крайней мере, немного).Если это не вариант, всегда есть возможность обернуть B некоторым классом WrapperB
(это в основном та же идея, что и в классическом шаблоне адаптера ):
class WrapperB: public InterfaceB
{
B _b;
public:
WrapperB(/* some parameters */) : _b(/* same parameters */){}
// Here you need to implement all methods of
// InterfaceB and delegate them to the original method calls
// of _b. You should give them the same name and signature as
// the corresponding (non-virtual) methods in B.
// For example, if there is a method m2 in B,
// there should be a pure virtual method m2 in InterfaceB, and
// an implementation here like this:
virtual void m2(){ _b.m2(); }
};
WrapperB
будет содержать только очень простой и простой код делегирования метода, для которого вы можете опустить модульные тесты.И вы должны использовать WrapperB
вместо B
, когда вы собираетесь использовать его вместе с A. Но вы получаете отлично тестируемый модуль class A
.
Другой (возможно, даже лучше)вариант заключается в построении класса WrapperB таким образом, что вы вставляете ссылку на объект B извне в него:
class WrapperB: public InterfaceB
{
B& _b;
public:
WrapperB(B& b) :_b(b){}
// implement InterfaceB methods as above
virtual void m2(){ _b.m2(); }
}
Вы можете использовать его так же, как это:
B b;
A a(WrapperB(b));
FakeB fb;
A a_for_test(fb);