
586
Chapter 23 Test Double Patterns
Example: Behavior-Modifying Subclass (Substituted
Singleton)
Suppose our getTime method was declared to be private
8
or static, fi nal or sealed, and so
on.
9
Such a declaration would prevent us from overriding the method’s behavior
in our Test-Specifi c Subclass. What could we do to address our Nondeterministic
Tests (see Erratic Test on page 228)?
Because the design uses a Singleton [GOF] to provide the time, a simple
solution is to replace the Singleton during test execution with a Test Double
Subclass. We can do so as long as it is possible for a subclass to access its
soleInstance variable. We use the Introduce Local Extension [Fowler] refactoring
(specifi cally, the subclass variant of it) to create the Test-Specifi c Subclass. Writ-
ing the tests fi rst helps us understand the interface we want to implement.
public void testDisplayCurrentTime_AtMidnight() {
TimeDisplay sut = new TimeDisplay();
// Install test Singleton
TimeProviderTestSingleton timeProvideSingleton =
TimeProviderTestSingleton.overrideSoleInstance();
timeProvideSingleton.setTime(0,0);
// Exercise SUT
String actualTimeString = sut.getCurrentTimeAsHtmlFragment();
// Verify outcome
String expectedTimeString =
"<span class=\"tinyBoldText\">Midnight</span>";
assertEquals( expectedTimeString, actualTimeString );
}
Now that we have a test that uses the Substituted Singleton, we can proceed
to implement it by subclassing the Singleton and defi ning the methods the
tests will use.
public class TimeProviderTestSingleton extends TimeProvider {
private Calendar myTime = new GregorianCalendar();
private TimeProviderTestSingleton() {};
// Installation Interface
static TimeProviderTestSingleton overrideSoleInstance() {
// We could save the real instance first, but we won't!
soleInstance = new TimeProviderTestSingleton();
return (TimeProviderTestSingleton) soleInstance;
}
// Configuration Interface used by the test
8
A private method cannot be seen or overridden by a subclass.
9
This choice prevents a subclass from overriding the method’s behavior.
Test-Specifi c
Subclass