C++ Dependency Injection, Part Deux

Last time I talked about a concept called Dependency Injection from the Java world, and compared it to Policy Based Design from the C++ world. The techniques that Java designers have used Dependency Injection for very easily ‘port’ to the Policy Based Design world – and one of these techniques, used in testing, is the idea of a mock framework. Mock frameworks are objects that ‘look, taste and smell’ like normal objects, but are used for purely testing purposes only and are useful in that the user can very closely control their state.

This time I’d like to go more into depth on a possible way to utilize Generic Dependency Injection, otherwise known as Policy Based Design, to build a mock object framework. I hope to show you that there are a few, for lack of a better term, ‘hacks’ that work very well for testing. They are hacks in that they aren’t all that pretty, however, I’d much rather utilize them to help keep testing concerns in testing code, rather than let our design and product reflect our testing procedure.

(On that note, I recall reading a post motivated by Test Driven Development and the creation of Mock Object frameworks, and the question of how to test private state. The answer the blogger gave was “make everything public”. In a world driven by tests, encapsulation takes a back seat. For shame, Java developers 🙂

Two important influences come from the Python world that I want to discuss. One is “Duck Typing” and the other is turning a compile time bug into a runtime bug on purpose. Duck Typing is a form of weak typing who’s premise is “If it quacks like a duck, it’s a duck.” That is, if I’m writing a method that requires an argument X and requires that X have a method of it’s own, called foo, then that’s all I need. I don’t need X to satisfy any type constraints, I just need to know that I can call X.foo() and not crash. This doesn’t even require a check for foo, as it’s considered bad form to call hasattr(X,”foo”) before a call to foo. Instead, good Pythonistas call first and ask questions later – basically by wrapping anything considered risky in a try/except block, and dealing with the attribute error raised by calling a method that doesn’t exist there.

Many people have noted that C++ templates are indeed very similar to Duck Typing. Absolutely no assumptions are made on a template, so if you have an X of some templated type, and you call X.foo, then the compiler just assumes you’ve done your due diligence and added that method in there somewhere. Pity on the designer who hasn’t, as a few pages of cryptic compiler errors are your reward. While C++ doesn’t allow this error to propagate into runtime like Python does, it does ‘weaken’ inheritance a bit. In Java, we use dependency-injection with object hierarchies, so we know whatever object we create on the other side fits some interface. C++ does not have that constraint(feature). This frees us up from some busy work of having to implement every single method on a large interface for each mock object, or enforcing some inheritance structure, which keeps tests light and easy to build.

(C++0x will have ways to levy interfaces on templates, called Concepts. However, these interfaces will be much more lightweight. It will be more in the style of the user asking “Here’s what I require” rather than the library telling “Here’s what I provide”. This will clear up many of the more cryptic template errors, as well as formalize STL concepts like the forward iterators, among other things, without the overhead of object hierarchies.)

In Python, there are no such things as interfaces or abstract base classes. Instead, interfaces are more or less defined by convention – one of these conventions is the idea of an ‘abstract method’ who’s sole purpose is to throw an exception if anyone calls him. They’ve effectively moved a compiler check into runtime, for better or worse. In the case of our tests, it’s for better.

The first thing we want to do is create a base mock class for every type we want to mock out. This type will resemble a Python ‘abstract’ class. It will inherit from all abstract base classes that our normal object does, and it will fulfill every abstract method – except every method will be nothing but throwing an exception.

Using this class as our ‘canvas’, we can now inherit one more time from this new mock object for any particular test we want to run. If we are testing our shape object’s ‘draw’ method, and we know(since we’re the designers) that shape’s draw calls a method on a ‘screen’ object called ‘getGraphics’, then we in turn just have to override one of our mock screen’s methods. The rest will still resolve to runtime exceptions. That way, we create very light mock objects for each test – in fact, we can create an entirely new hierarchy of types for each test, filling in the methods we want information on. For example:

namespace test1Detail {

class ScreenTest : MockScreen {

virtual Graphics getGraphics(){ … }

};

typedef Shape<ScreenTest> TestShape;

}

BOOST_AUTO_TEST( test1 ){

test1Detail::TestShape myShape;

…run test…

}

I now can add whatever behavior I want inside of getGraphics. And if my test calls any method BUT getGraphics, which is the only one I implemented for the test, I get a runtime error that will most likely be logged by my unit test library.

What kinds of things might I put inside these mock methods? Well lets say I am mocking a map object, like std::map. The object I’m testing is supposed to receive a message, and create a new object in it’s map with a key that’s also contained in the message.

Lucky for me I control the object at all points! I know exactly what message I’m sending to the object I’m testing, and I can set the key value to be whatever I want. Then, only a few lines away, in my detail namespace for that test, I’ve created a brand new class that ALSO has the key value I’m testing hard coded. In this case, I can override operator[] to make sure I’m attempting to add the right key.

Your mock objects that you intend to plug into testing are complete throwaway objects – you will only use the type once, so there’s really no gain in ‘designing’ the class well. In other words – make everything public. Hell, make everything public and static! Many of my mock objects are just a single method and a few static booleans I use as flags. You need to make most things static inside your mock objects so that you can access them from the type level. Look at the above example, and then think about how you’d check and make sure getGraphics was called with a certain argument.

…virtual Graphics getGraphics(int key){

if(key == 100){ //hard coded value

ScreenTest::KeyTestPassed = true;

} // rest of method

Now, at my TEST level, inside my BOOST_AUTO_TEST function, I can access the flag I just set, via the same resolution.

Test1Detail::ScreenTest::KeyTestPassed

For each test, we are creating a completely different type, not just a new object. And since we know exactly how many times this type will be instantiated, we can hard code different values and checks cowboy-style. The mock objects are completely throwaway, and are meant to simply be the quickest, dirtiest way to run our tests. Because the quicker we can write tests, the more test we are inclined to write.

Next time I hope to go over how we can extend our simple mock objects, giving us the ability to access individual instances. I also would like to make a few comments on applying RAII and review the template-know-how to make more advanced general use tests. Until then!