Test Doubles In Action

Test Doubles In Action

In the last post, I talked about Test Doubles and some various types that we can use and how to implement them. The next obvious question is how do we actually use them in our tests.

Dependency Injection

Understanding Test Doubles first requires understanding the concept of dependency injection. This is where the calling code doesn’t know about which specific object it will use, it just knows about the interface (ie in LabVIEW the “virtual” parent class – a class with no private data and where all methods are dynamic dispatch with no implementation). In the case of our example, this is ISerial. The calling code supplies the specific concrete object to use.

dependency injection is a technique whereby one object supplies the dependencies of another object. “

Wikipedia
Here is the LabVIEW Class Hierarchy

The first step is to set up your class hierarchy so that your doubles inherit from the same “interface” class as your production class (in this case the Humble serial class). In this example, we do this by creating an ISerial Class.

Here is a UML Class Diagram showing the relationships between the Production Class (HumbleSerial), the “Interface” class (ISerial) and the various Test Doubles.

“Code to the interface, not the implementation.”

OOP Programming Maxim
This is where the dependency injection happens. Before doing anything with the ISerial Port Object, the calling code must supply an appropriate concrete child class. Note that all the Serial Driver Class knows about is the ISerial class, not the concrete children.

Example Unit Tests

Here we use a Responder which we preprogram with the data it should return.
Here we use a saboteur to make sure that an error condition is caught and passed out.
Here we create a queue to capture the data written to the serial port, which we pass off to a Spy.