Blunts
Test-Driven Design is facilitated by several kinds of objects which substitute for real objects and which exercise the system or probe the behavior of other objects. This matters because real systems use objects that you don’t want the test to exercise. If every test creates elaborate windows and reads large files, your tests will be slow. If the system involves alarms or databases or sprinkler systems, your tests are going to be uncomfortable.
Two categories of test objects are widely known.
- Stubs behave like the real object, but substitute simple or canned behavior for the real thing. For a test, you might stub out a database with an object that accepts your query and feeds back a single precomputed response. For an alarm system, you might have a SprinklerController that (a) turns on sprinklers all over the building to extinguish the fire, (b) rings loud alarms, and (c) returns the string “OK” if the sprinklers are operating, or “FAIL” if they aren’t. The TestController could simply return “OK” without making you wet.
- Mocks are mock objects that automatically emulate the interface of a real object and that return exactly what you specify.
I’d like to propose a third useful category, the Blunt Object. A Blunt is a subclass of a real object; it does everything the real object does except it removes behavior you don’t want in a test.
For example, a BluntSprinklerController is a subclass of a real SprinklerController and inherits almost all of the parent class behavior. But we do override two methods, RingAlarm() and ActivateSprinkler() — in each case doing nothing instead of actually making noise and extinguishing fires.
Blunts are as easy to write as stubs. Indeed, they’re often easier, since often you only need to override one or two methods. Blunts let you run tests with real collaborators, potentially reducing integration problems. Of course, Blunts have drawbacks:
- Blunts are only useful if the underlying object is not too difficult to construct.
- A blunt object derived from a very dangerous object, like the SprinklerController, requires careful analysis to ensure that it really is blunt and safe to use.
Blunts are a very simple idea, of course, and everyone who writes tests is likely to have used them. But I’ve not seen them discussed explicitly and I do like the name.