It’s been a while. I have been heads down on a new project (more about that some other time), and have not got around to posting. Without further ado here is the follow up post to TDD and Hart To Test Areas, Part 1.
Depend upon Abstractions
The Gang of Four’s first principle is to program against
abstractions not implementations. If we use abstractions then we can solve the
hard-to-test problem by implementing the abstraction in terms of the
hard-to-test dependency in production, but with a simple-to-test dependency in
test. So we could use an IDatabase to
abstract out our interaction with the Db, using concrete Ado.Net classes in
production, but replace it with an in-memory collection for testing. Jeremy
Miller summarizes this approach as ‘isolate
the ugly stuff’.
We need to show some rationality here. No one wants IString,
everyone wants IDatabase, and we probably don’t need an ICustomer, but we
might. The advantage of TDD is in flushing out where ICustomer is useful by
exercising the SUT. So when designing for testability we need to
think about which dependencies we want to allow to be concrete, and which won’t
don’t. Different schools of programming make different value judgments here.
Classicist approaches tend to avoid replacing all dependencies, focusing
instead on ones that are needful to support extensibility and layering.
Design principles should help us identify when to use
interfaces and these tend provide the opportunities we need to use abstractions
to isolate hard-to-test code.
A layered architecture also creates a need for abstractions.
While the layers must communicate, like a layer cake higher lays may depend on
lower-layers but not vice-versa. To effect this, higher layers in our
architecture should depend on an abstraction exposed by the lower layer, not a
concrete type. The two layers can communicate via the agreed contract, but the
higher layer has no dependency on the lower layer. Robert Martin’s Dependency Inversion
Principle states that High level modules
should not depend upon low level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon
This dovetails with hard-to-test areas as layer boundaries
often co-inside with hard-to-test areas such as the UI or access to external
systems. So using abstractions when we layer helps us to achieve testability. To
ensure cohesion we often talk to a façade when we cross a layer boundary, which
hides the complexity of the other layer, and this again simplifies testing, by removing
the need to create the objects that implement the façade as part of our test
In Agile Principles, Patterns, and Practices in C# Robert
Martin describes the Open-Closed Principle as “Software entities (classes, modules, functions, etc.) should be open
for extension but closed for modification.”
To achieve this ‘impossible thing before breakfast’ we use
polymorphism. By creating an abstraction (either explicitly by using an
interface or abstract base class, or implicitly by marking methods as virtual),
we both define a contract allows us to define how we interact with that type -
it is closed for modification – but allows many concrete implementations of
that type – we are open for extension.
Note that an abstract type
The extension points provided by abstractions are ideal for testing as they
allow us to replace depended upon components for testing. Michael Feathers
calls these points seams: A seam is a
place where you can alter behavior in your program without editing in that
place. A virtual method can be especially useful in legacy code to
create a point of extensibility to test code, where we cannot reasonably extract or introduce an interface to allow us to do so.
The concept of replacing a hard-to-test implementation with
an easier to test one was originally called mocking. This term has become
overloaded so Gerard Meszaros has suggested replacing it with the term Test
Double of which a Mock is only one category. The term Test Double is meant to
convey the idea of the Stunt Double who replaces the actor for dangerous
scenes. There are two different scenarios in which we want to use a
- Where we need to control the inputs into a SUT, but there is
no observation point for us to do so. For example, if we access a repository in
our SUT to return an entity from the Db, such as a Customer, so that we can
retrieve some value from the Customer, we need to have some way of controlling
what is returned from our repository as that forms an input into the SUT.
- Where we need to monitor the outputs from a SUT, but there
is no observation point for us to do so. For example if we are calling an
external web service from our SUT then we want to monitor the arguments sent to
that service, but we don’t want to actually make the call.
Working with Indirect Inputs
Controlling the inputs from the Depended On Component (DOC) to the System Under Test (SUT) is needed when because we want to control the flow of execution within the
SUT, but we do not care about the outputs to that DOC. We may want to control
execution to allow the ‘happy path’ but we might want to control execution to
test the error path too, by providing appropriate input.
The need to control indirect inputs occurs
because where we have difficulty setting up the values returned by the DOC to
the SUT. Often this occurs because the DOC is in hard-to-test area (Db, file
system, across network or process/AppDomain boundary). Such a DOC should
generally be represented by an abstraction – depend upon abstractions – we have
seam for our test in replacing the ‘ugly stuff’ in the DOC with a test double.
There are two patterns for replacing a DOC
when we need to work with indirect input: stub and fake
A stub is a light-weight implementation of
an interface. With a stub we just want it to return some values in response to
a method call or property access on the DOC that allows the method on the SUT
to continue processing. A lot of ‘mocking’ frameworks now have first class
support for stubs.
In the following example an Insurance
Product is our SUT which uses the DOC of a rating service and asks the DOC for
the version of the rating plan that is in force. Here we are using Rhino Mocks
support for automatically generating a stub.
public class Using_A_Stub_To_Replace_A_Depended_Upon_Component
ratingService = MockRepository.GenerateStub<IRatingService>();
Product product = new
RATING_PLAN_VERSION = 5;
ratingService.RatingPlanVersion = RATING_PLAN_VERSION;
int ratingPlanVersion =
ratingPlanVersion, “Expected the rating plan
to be the one from the rating service”);
public class Product
ratingService = null;
this.ratingService = ratingService;
We use a test stub where we need to control
the indirect inputs from a DOC to the SUT, but we do not need to verify the
indirect outputs. A stub can be useful to force execution of certain paths in
the SUT, by returning values that direct the SUT down that path. This can be
useful for error testing.
A stub returns a value to the SUT from the
DOC, but cannot stand in place of the DOC. It is often incomplete and usable
only in the context it was set up for. A fake is in contrast is a lightweight
version of the DOC. It behaves in a similar fashion to the original. We
commonly use a fake where we have multiple interactions with the DOC in the SUT
i.e. load and retrieve or because we need a test double across a number of test
fixtures and we want to remove duplicate stubs. Fake or in-memory database and
fake web service are common uses.
In this example we want to replace a
service that we depend upon that manages endorsements, with a fake. Whereas the
stub is dumb the fake has the semantic of the DOC. The FindEndorsements method
on the fake loops through its collection of endorsements and returns those that
match the required type. However, while our production implementation might
source its list of endorsements from a Db, our fake just uses an in-memory
collection. This isolates us from an y Db issues like shared fixture or slow
public class Using_A_Fake_To_Replace_A_Depended_Upon_Conponent
endorsementService = new FakeEndorsementService();
var product = new Product(endorsementService);
NO_OF_MANDATORY_ENDORSEMENTS = 12;
NO_OF_OPTIONAL_ENDORSEMENTS = 2;
mandatoryEndorsements = product.FindMandatoryEndorsements();
Assert.AreEqual(12, mandatoryEndorsements.Count, “Expected the number of mandatory endorsements to
equal those added”) ;
private List<Endorsement> CreateEndorsementList(int noOfEndorsements, EndorsementType
endorsements = new List<Endorsement>();
for (int i = 0; i
< noOfEndorsements; i++)
private List<Endorsement> CreateMandatoryEndorsementList(int noOfEndorsements)
return CreateEndorsementList(noOfEndorsements, EndorsementType.Mandatory);
private IEnumerable<Endorsement> CreateOptionalEndorsementList(int noOfEndorsements)
return CreateEndorsementList(noOfEndorsements, EndorsementType.Optional);
public class Product
ratingService = null;
this.ratingService = ratingService;
this.endorsementService = endorsementService;
public List<Endorsement> FindMandatoryEndorsements()
public class FakeEndorsementService : IEndorsementService
private List<Endorsement> endorsements;
public List<Endorsement> Endorsements
endorsements = value;
public List<Endorsement> FindEndorsements(int productId, EndorsementType
matchingEndorsements = new List<Endorsement>();
endorsement in endorsements)
if (endorsement.Type == endorsementType)
Checking on Indirect Outputs
We need to check outputs where what we send
to the DOC needs to be tested. Usually this occurs because we have no means to
retrieve the message that was sent to the DOC by the SUT in the verification
phase of our test, but need to verify that message to ensure that our code
works correctly. In other words we are not testing a change in state to our
SUT, but a message sent to a DOC.
When we need to record the messages from
the SUT to the DOC there are two options: a spy and a mock.
A spy allows us to record the changed state
of the DOC and then use an assertion to confirm that state within our test.
As such it dovetails well with the normal
test model. A spy is especially valuable where we do cannot predict all of the
values passed to the DOC ahead of time, and instead need to confirm them, often
against the state of the SUT when the test has finished exercising the code.
A self-shunt can be a quick way to
implement a spy. The test fixture implements the interface for the DOC and
records any interactions in fields on the class. Confirmation then involves
testing the fields. Be aware that shared fixture state means that you need to
use an explicit setup to clear that shared state if more than one test uses the
In the following test we check the document
job passed to the document service when we bind a document. Within the demo we
are just checking for the existence of the job, but in a real test we could
examine the job to determine if it met our expectations of what should be
public class Use_A_Test_Spy_To_Replace_A_DOC : IDocumentService
var submission = new Submission(this);
//verify – a real test would do more testing around what the
this.job = job;
public class DocumentJob
public class Submission
private IDocumentService service;
this.service = service;
DocumentJob job = new
A mock is useful when we want to confirm
the sequence and number of messages to the DOC, specifically the method calls
and the arguments passed to them. A mock
is intrusive in that it specifies the interaction that the SUT should have with
the DOC and confirms that the interaction meets that specification. It is thus
less amenable to refactoring because it has knowledge of the implementation of
Mocks tend to be implemented using frameworks,
so that makes them cheap to write, but the problem here can be a temptation to use
mocks out of their appropriate context just because we have a framework for
them. The issue here is we can end up with over-specified software that is
difficult to refactor, because the tests lock in our implementation choices.
Using ‘loose replay’ semantics, which allow
mocks to respond without raising an error if calls are not made, can reduce the
coupling between specification and implementation where appropriate.
A mock differs from a spy in that a mock
forces us to specify the expected interaction before we exercise the SUT, not
after. It may be better to use a spy where you are
uncomfortable with the test specifying the implementation of the SUT.
In this, contrived, example we call an
external OFAC service to search for our customer. We don’t return the result,
but set a flag which is used in later rules. We want to test our output to the
OFAC service, which is third-party to confirm that our interaction is correct.
public class Use_A_Mock_To_Replace_A_DOC
mocks = new MockRepository();
oFACService = mocks.CreateMock<IOFACService>();
//strict replay semantics
Account newClient = new
newClient.FirstName = “Ian”;
newClient.Surname = “Cooper”;
public class Account
private bool onWatchList;
public string Surname
onWatchList = oFACService.SearchSDNList(ToString());
public override string ToString()
return FirstName + ”
“ + Surname;
Inversion of Control
Note that in order to replace the DOC with
a stub; we must support Dependency Injection i.e. the instance of the DOC used
by the DOC must be supplied to it.
We could do this directly in our code;
before we create the object we create its dependencies. The problem here is
duplicating all that code to create our dependencies.
We could create a service locater that we
can ask for instances of common dependencies. This removes the duplicate code,
and allows us to, for example, provide different implementations of the DOC but
creates an additional dependency for the class, on the Service Locater.
Finally we could use an Inversion of Control
(IOC) container. With an IOC container we ask the container for the finished
object. Inversion of Control is sometimes called the Hollywood Principle or
“don’t call us, we’ call you”. We are using IOC in this context because we no
longer have a dependency on a Service Locater, but hand off to an assembler and
ask it to inject our dependencies. The framework creates us instead of us
creating using the framework. Using an Inversion of Control container, such as
Windsor, simplifies the creation of objects with their required dependencies.