Let’s say I have the following class:
class Foo
{
public:
Foo()
{
Bar();
}
private:
Bar(bool aSendPacket = true)
{
if (aSendPacket)
{
// Send packet...
}
}
};
I am writing a test harness which needs to create a Foo object via the factory pattern (i.e. I am not instantiating it directly). I cannot change any of the factory instantiation code as this is in a framework which I don’t have access to.
For various reasons I don’t want the Bar method to send packets when running it from a test harness.
Assuming I cannot call Bar directly (eliminating potential solutions like using a friend class), what is an elegant design pattern to use to prevent packets being sent out when running my test harness? I definitely don’t want to pollute my production code with special cases.
You want
Barto send a packet in ordinary operation, but not in testing. So you will have to have some code which runs when you callBarduring testing, even if it’s an empty function. The question is where to put it.We can’t see the code inside the
if(aSendPacket)loop, but if it delegates its work to some other class then we can make the substitution there. That is, if the loop isso that the work is done by the `packetHandler class:
then we can make a “mute” version of the
packetHandlerclass. (Some would call it a stub or a mock class, but there seems to be somedebate about the definitions of these terms.)When testing
Foo, compile this version ofpacketHandlerand link it in. The factory won’t know the difference.If, on the other hand, the code for sending a packet is spelled out in
Foo, with no way to head off the behavior outside theFooclass, then you will have to have a “testing” version ofFoo.cc(there are other ways but they are clumsy and dangerous), and the best way to do that depends on the details of your codebase. If there are only a couple of “untestable” features like this, then it’s probably best to putFoo::bar(...)in a source file by itself, with two versions (and do the same for each of the other special methods). If there are many then may be worth deriving a factory class specific to testing, which will construct instances of, e.g.class testingFoo : public Foowhich overridesBar. After all, this is what the abstract factory design pattern is for.