Tag Archives: Test Driven Design

Designing inter-object protocols using mocks

The intent of my recent paper, was to demonstrate how mock objects could be used to discover roles, and design the communication protocols between objects. The following content did not make it to the final version, I think these are important points so i will describe them here.
Distinguish between an Object’s Internals and its Peers
It is important to distinguish what the internals of an object are and who are its peers that it communicates with.  An object’s internals are usually created and used within an object. In my example the fact that the Register object collaborates with the Sale object to calculate the receipt total is hidden. Peer objects, on the other hand, aren’t hidden inside the object, they are a passed in to the object, either through the constructor as a dependency or through a setter (if the peer object is a policy or notification object).
All interactions internal to an object should be hidden from the client code that uses the object; likewise a unit test should not be concerned with the internal details of the object under test.
Exposing an objects internals details to simply test every aspect of a class in pure isolation, causes the tests to be overly coupled to the implementation details of the object. You will find tests using mock objects highlight these design issues very quickly, one hint is when you find that the production code, simply mirrors the expectations you wrote in the test code, this  obviously makes tests very brittle since they overly coupled to the implementation details of the object under test.
This could be addressed by changing the behavior of the mock framework to ignore all calls between the object under test and its collaborator unless explicitly specified.  However this does not address the underlying weakness in the design of the protocol between the object under test and it collaborators, it fact it simply hides all complex inter-object protocols.
Nat Pryce coined the phrase “A composite object should be simpler than the sum of its parts.”  An object should provide a simpler API to its clients, rather than simply exposing all its internal objects through its API. I find this is a good heuristic to follow when deciding what should be internal to an object and what its peers should be. On the other hand we should ensure we are not hiding the wrong information inside an object. Well-designed objects should be context independent and not tied to its environment; objects tightly coupled to its environment will be difficult to instantiate in a unit test. I find the rapid feedback provided by tests is invaluable when designing objects.

Why did I chose to use NMock ?

A lot of people ask me why i chose NMock, for this introductory article, I felt NMock 2 is the best choice of API,  because it works best within the context of the article. It has an expectation-based API, which makes designing object communication the focus of testing. Its expectation API acts as a domain specific embedded language that clearly, precisely, and declaratively describes object communication. I also find that NMock2 provides a highly detailed explanation of what has failed, which allows for quick error diagnosis and resolution.

I’m sure many people will have different opinions on this but I have avoided using mock frameworks that use the popular Arrange, Act, Assert (AAA) style because I find that it does not get you started off by thinking about the contracts or communication protocols between objects. With AAA-style mocks I find it’s easy to overlook design flaws in your inter-object communication.

The main drawback of NMock is the use of strings to identify expected methods makes refactoring harder.  This becomes less of an issue when a code based is designed around well-defined roles and responsibilities, containing narrow role based interfaces, which are used more locally.

Test Driven Design using mocks- Lessons Learnt (Part 2)

This is a follow up to my previous post. In this somewhat contrived example we are building a point of sale system and there is a requirement to print out a receipt for a sale, which includes item details, total taxes and the total amount due.
Using Rinho mocks Here is the first test I wrote initially, which drove out the need
for a Renderer role, whose responsibility is to render the contents of the receipt
onto an output device

[TestFixture]
public class SalesTests
{
private MockRepository mockery;

[SetUp]
public void BeforeTest()
{
mockery = new MockRepository();
}

[TearDown]
public void AfterTest()
{
mockery.VerifyAll();
}

[Test]
public void ShouldbeAbleToPrintReceiptForASaleWithNoItems()
{
var sale = new Sale();
var renderer = mockery.StrictMock<IRender>();
renderer.Render(”Total Taxes: 0.00 \n Total: 0.00″);
mockery.ReplayAll();
sale.PrintReceiptOn(renderer);

}
}
the implementation needed to pass the above test was as follows

public interface Renderer{
void render(String s);
}
public class Sale {

public void PrintReceiptOn(IRender renderer)
{
renderer.Render(”Total Taxes: 0.00 \n Total: 0.00″);
}

By driving the design test first I was able to discover the need for an object to play the Renderer role, using mocks I was able to drive out interface for the Renderer role.
But I also realised later the above test was brittle and over specified, because
the test was very tightly coupled to the implementation, because the conversation between the objects was not at the right level.
for instance if I changed the implementation of printReceiptOn on the Sale object to

public void PrintReceiptOn(IRender renderer)
{

renderer.Render(”Total Taxes: 0.00″);
renderer.Render(”Total: “);
renderer.Render(”0.00″);
}

The test will break (because the test specifies the Render message be sent to the renderer only once with a specific argument) although the implementation is
quite valid. So the test is tightly coupled to the implementation
Now we could try addressing the symptom by defining a looser constraint on the test as shown below

[Test]
public void ShouldbeAbleToPrintReceiptForASaleWithNoItems()
{
var sale = new Sale();
var renderer = mockery.StrictMock<IRender>();
renderer.Render(”Total: 0.00″);
LastCall.Repeat.AtLeastOnce().IgnoreArguments();
mockery.ReplayAll();
sale.PrintReceiptOn(renderer);

With the above either of my previous implementation would make the
test pass. however it doesn’t test the right data was being rendered.

To ensure that the right data was being rendered
We could write a state-based using a collecting stub to verify the data being
rendered is correct as shown below
[Test]

public void VerifyReceiptContentsForSaleWithNoItems() {
TestRenderer renderingDevice = new TestRenderer();
sale.printReceiptOn(renderingDevice);
Assert.assertEquals(”Total Taxes: 0.00 \n Total: 0.00″,
renderingDevice.GetContents());

}

where TestRenderer is a collecting stub which is implemented as follows

public class TestRenderer : IRenderer {
private String contents;

public void Render(String s) {
contents += s;
}
public String GetContents() {
return contents;
}
}
At this point I was questioning the usefulness of a mock, it seemed I was better off using a state based test and using a colleting stub to verify. The brittleness of our initial interaction based test, indicated an underlying design issue, interaction was not specified at the right level. The trick here is to design interactions that are meaningful to the calling object, this leads to interface discovery, (and this is one of the reasons why you should not mock 3rd party API’s). Now Render(string s) is not a meaningful message to the Sale object to be sending to the Renderer, the Sale object knows about items, taxes and total so What would have been more a meaningful interaction (conversation ) between the Sale object and Renderer would be to specify the interaction in terms of taxes, items and total, as shown below.

[Test]
public void ShouldbeAbleToPrintReceiptOnAPrinterForSaleWithNoItems()
{
renderer.RenderTaxes(0.0m);
renderer.RenderTotal(0.0m);
mockery.ReplayAll();
saleUnderTest.PrintReceiptOn(printer);
}
public interface Renderer {
void RenderTotal(decimal total);
void RenderTaxes(decimal taxes);
}

the following is now the implementation of the PrintReceiptOn method of the Sale Object

public void PrintReceiptOn(IRender renderer)
{

renderer.RenderTaxes(totalTaxes);
renderer.RenderTotal(total);
}
This is where mock objects are so useful as they aid in the discovery of interfaces and quickly give us feedback in the form of brittle tests when interactions between objects are poorly designed.

Test Driven Design using mocks – Lessons learnt (Part 1)

Lesson 1 – “Specify conversations between objects an abstract enough level”

A common complaint with using mock objects is that interaction based tests ties your tests to the implementation details of the production code and interaction based tests are tracking the implementation of the method you’re testing. I felt this many times previously, every time I refactored my production code some of my tests seem to break even though, functionality of the object remained the same. Often mocks and interaction based testing are blamed for brittle tests. I have come to realize any brittleness exposed by interaction based tests is just a symptom of an over specified test or their is an underlying design issue because of a weak interaction model.

Interaction tests will be brittle and tied to the implementation if you dont specify interactions at the right level, and your tests will quickly let you know. After spending time doing some development in the Smalltalk world, i rediscovered that OO is all about message passing (object interactions). So a good OO model must have a good interaction model, with this in mind i have come to realize that the key to interaction based testing is specifying interactions (or conversations) between an object and its collaborators at the right level. An object should tell its collaborator what it should get done and not how it should do it. This drives us not to include even a hint of implementation detail when designing our interactions between the object under test and it collaborator, this forces us to create collaborator interface at an abstract enough so that no implementation details gets in the way, this leads to what is often called interface discovery of the collaborating objects, and is a great exploratory way to design the interface of collaborators and distribute responsibilities between objects and mocks are a vital tool to do this. This is what Steve Freeman and Nat Pryce have been telling us all along, but its only now I’m starting to understand this. However i also learnt not to use mocks everywhere, generally if I cannot model interactions between an object and its collaborator at an abstract enough level that made sense to the calling objects domain, it generally means i’m unable to define a clear role interface for the collaborating object, then in this case i would not use mocks at all, rather I tend to use a real object or a stub and test a cluster of objects together.
So what do I mean by “Specifying conversations between objects an abstract level”. I will try explaining by giving an example in the next post