On 9/14/06, Scott Meyers <usenet@aristeia.com> wrote:
My understanding is that the ability to drop in mock objects requires
programming to an interface that can be either a "real" object or a mock
object, which in turn suggests using either a template parameter or a
base class. Suppose, for example, you have this:
class BigHonkinHairyClass {
... // expensive to construct
};
and you want to implement some function f that takes a
BigHonkinHairyClass as a parameter. The straightforward declaration
would be
void f(BigHonkinHairyClass& bhhc); // maybe const, doesn't matter
But now it's hard to drop in a mock. So I assume you'd modify the
interface to be either
template<typename T>
void f(T& bhhc); // T must more or less model
// BigHonkinHairyClass
or this:
class BigHonkinHairyBase {
... // interface to program against --
}; // uses virtuals
class BigHonkinHairyClass: public BigHonkinHairyBase { ... };
class MockHonkinHairyClass: public BigHonkinHairyBase { ... };
void f(BigHonkinHairyBase& bhhc);
Is that correct? In other words, you'd come up with an interface that
let clients do what they wanted but that was also mock-friendly for
testing purposes? That is, you'd take testability into account when
designing your client interface?
I design interfaces like that, but not for testing - it's called the Inversion Principle. How often do you really need a BigHonkinHairyClass ? Often, you really just need a subset of its interface. So define that sub-interface. Sometimes use templates, sometimes inheritance, etc.
Maybe that doesn't apply for every function f() (ie a different interface for each function!?), but I thought the Inversion Principle would be worth mentioning; YMMV.
Tony