26 December 2006

Mock Objects is a Technique, Not a Technology

George Malamidis recently proposed an alternative to mock objects in Groovy. Instead of using mock objects you can just use Groovy's Expando class to make an object that behaves like another type and checks that it is being invoked as expected.

But... that is a mock object!

Mock objects are not a specific technology, such as jMock or EasyMock they are a technique for the test-driven development of object-oriented code that follows a Tell, Don't Ask design style.

You can write mock objects with a framework, by using the reflection and metaprogramming facilities of a dynamic language, by coding everything by hand, or by generating the code at compile time. Whatever floats your boat.

However, faking out the mocked type is only a small part of what a mock object framework like jMock does. In fact, of the 2487 lines of code that make up jMock 2 only 34 are required to perform what we whimsically call "imposterisation". The remainder provide syntactic sugar to ensure the test code clearly expresses the intent of the test, let the programmer precisely specify the expected interactions between objects and generate clear diagnostics when tests fail. This functionality is vital if tests are to be helpful during the ongoing development of the code.

14 December 2006

Only Mock Immediate Neighbours (i)

We often see tests that are hard to understand because they drive code that calls objects returned from other objects. Here's an example of code that calls a chain of objects.
public void allUnresolvedIssues(IssueHandler handler) throws Failure {
 TicketManager ticketManager = connections.getTicketManager();

 ticketManager.lock();
 try {
   IssueManager  issueManager = ticketManager.getIssueManager();
   Iterator issues = issueManager.allIssuesIterator();

   while (issues.hasNext()) {
     Issue issue = issues.next();
  
     if (issue.isUnresolved()) {
       handler.accept(issue);
     }
   }
 } finally {
   ticketManager.unlock();
 }
}
This is a minor offender, but even so it gets a list of Issues from an IssueManager, which it gets from a TicketManager, which it gets from a Connection. The important part of the method is the filtering of the issues, but to get there it has to navigate three objects, including locking and unlocking the TicketManager. We might have to do something like this to test it.
public void testFiltersUnresolvedIssuesFromIssueManager() throws Failure {
 final ArrayList allIssues = new ArrayList() {{
   add(issue1Unresolved);
   add(issue2);
   add(issue3Unresolved);
 }};

 expects(new InAnyOrder() {{
   allowing(connections).getTicketManager(); will(returnValue(ticketManager));

   expects(new InThisOrder() {{
     one(ticketManager).lock();
     one(ticketManager).getIssueManager(); will(returnValue(issueManager));
     one(issueManager).allIssuesIterator(); will(returnValue(allIssues.iterator()));
  
     one(issueHandler).accept(issue1Unresolved);
     one(issueHandler).accept(issue3Unresolved);
  
     one(ticketManager).unlock();
   }});
 }});

 moreThanImmediateNeighbours.allUnresolvedIssues(issueHandler);
}
I find this confusing to read. First, too much of the test code is for setting up state to get to the interesting feature. Second, the test is exercising several things at once: locking and unlocking the TicketManager, querying the issues within the lock, and filtering the issues. If I want to test more conditions, such as when there are no issues or when something fails, I'll have to duplicate lots of irrelevant test code. I can extract that duplication into setup methods, but I think that's missing what the test is telling me. Another problem is that the test is, more or less, just reproducing the logic of the code, which means it's not adding much value and also makes it brittle when I want to refactor later—especially if I have many similar tests to change. This is a common reason given for not using Mock Objects and a plausible one when dealing with code like this. Let's see if I can break things up a bit. My first thought is that I can separate out everything to do with the TicketManager by extracting a method.
  public void allUnresolvedIssues(IssueHandler handler) throws Failure {
   TicketManager ticketManager = connections.getTicketManager();
  
   ticketManager.lock();
   try {
     retrieveUnresolvedIssues(ticketManager.getIssueManager(), handler);
   } finally {
     ticketManager.unlock();
   }
 }

 private void retrieveUnresolvedIssues(IssueManager issueManager, IssueHandler handler) {
   Iterator issues = issueManager.allIssuesIterator();
  
   while (issues.hasNext()) {
     Issue issue = issues.next();
    
     if (issue.isUnresolved()) {
       handler.accept(issue);
     }
   }
 }
Now I can see a bit more clearly the two activities going on here: getting hold of the issue manager, and retrieving issues from it. I can break these up into different, focussed objects. I could start from the current design and refactor, but I want to begin again to show the design process...

01 December 2006

Evolving a Domain-Specific Language in Java

I've uploaded our OOPLSA 2006 paper, Evolving a Domain-Speficic Language in Java which describes our experience of evolving from the mockobjects library to jMock (with jMock2 coming soon !). In particular, we write how things changed when stumbled on the notion that we were writing a language rather than just a library. Our one regret is that for copyright reasons we had to take out the cute dinosaur pictures we found before publication. We even found an Agilisaurus.

02 November 2006

Mock Object Clinic (I)

Dylan Smith has posted a comparison of testing with and without mocks. He makes some good points, but his example is flawed. In some kind of pseudocode, his test is like this:
Test
  test calculate pay
   mockEmployee := mock(IEmployee)
   employee := Employee( mockEmployee )
   startDate := Date(1, July, 2006)
   endDate := Date(31, July, 2006)

   expect once ( mockEmployee.labour(startDate, endDate) ) will returnValue( 40 )
   expect once ( mockEmployee.payRate() ) will returnValue( 48 )
   expect once ( mockEmployee.premium() ) will returnValue( 2)

   assertEqual( 2000, employee.calculatePay(startDate, endDate) )
with an implementation like this:
Employee( target ) implements IEmployee
 this.target := target

Employee.calculatePay( startDate, endDate )
 labour := target.labour(startDate, endDate)
 rate := target.payRate()
 premium := target.premium()

 return labour * (rate + premium)
Incidentally, both the real and mock Employees implement the IEmployee interface. The problems I see with this example are:
  • the Employee class isn't complicated enough to mock. It's basically a struct with a helper method. We don't usually mock simple classes that have no interactions with third parties
  • the record/playback style of mocking is too brittle. It's OK for the simple cases and to learn the approach, but we want to think in terms of expressing constraints between objects, not just simple matching.
  • everything's a getter. Mocks should push you towards a "Tell, Don't Ask" style of coding, where behaviour is passed around rather than data.
  • I find the double implementation of IEmployee confusing. The test doesn't really help to flush out the relationship between an Employee object and its neighbours
Off the top of my head, I think an alternative (contrived) example would be something like:
Test
  test reports pay to payroll
    timesheet := Timesheet()
      .set( Week(3), Hours(40) )
    employee := Employee( HourlyRate(50), timesheet )

    payroll := mock(Payroll)
    expect once (payroll.addEmployeeForWeek( employee, Week(3), Rate(2000) )

    employee.reportPayForWeekTo( Week(3), payroll )

Employee( hourlyRate, timesheet )
  this.hourlyRate := hourlyRate
  this.timesheet = timesheet

Employee.reportPayForWeekTo( week, payroll )
  payroll.addEmployeeForWeek(this, week,
                             hourlyRate.valueOf( timesheet.hoursForWeek(week) ))
Note that now the expectation doesn't have to return anything because we're sending a message to the payroll object. Also, more of the objects have behaviour on them and the employee has a more meaningful relationship with its neighbour than before.

21 October 2006

[jMock] Listening to Opinionated Software

David Heinemeier Hannsen coined the pithy term Opinionated Software to describe the design philosophy he follows in the development of Ruby on Rails:
Rails is opinionated software. We make things that we consider good style easy to do and bad style hard. Or rather, we make good style beautiful and bad style ugly.
We have followed a similar approach in writing jMock. We describe mock objects and jMock as a design tool. jMock is designed to make some things easier to test than others so that doing test driven development with the jMock framework guides your code towards a style that we have found makes it easy to maintain in the long term and adapt to new, unexpected requirements. Code that is easy to test is composed of loosely coupled, cohesive objects and dependencies between parts of the system are made explicit and highly visible. Yes, you can use jMock's CGLIB plugin or Aspect Oriented Programming to get around jMock's limitations: to mock concrete classes and static methods or change the values of singletons and other global variables during a test, for example. However, we've found that when we find a need for one of those tools it's better to address the design problem than the testing problem. When the design problem has been addressed, the testing problem has gone away. We describe this as listening to the tests.

16 October 2006

When to ask instead of tell?

Mock objects work best with, and are designed to support, object-oriented code that is written in a Tell, Don't Ask style. However, that doesn't mean objects must, or even can, never ask each other for information. But apart from value objects and generic collection types, neither of which are stateful domain objects, I've found that I only need queries to search, sort and filter collections of objects. For example to filter non-managers out of a list of employees I'd need an isManager method on the Employee class:
Set managers() {
    Set managers = new HashSet();
    for (Employee employee : employees) {
        if (employee.isManager()) {
            managers.add(employee);
        }
    }
    return managers;
}
To use mock objects to test a method that only applies to managers you would stub calls to the isManager method of employees in the collection:
public void testOnlyAllowsManagersToTravelBusinessClass() { // for example
    Employee peon = mock(Employee.class, "peon");
    Employee manager = mock(Employee.class, "manager");
    
    Company company = new Company();
    company.addEmployees(peon, manager);
    
    expects(new InAnyOrder() {{
        allowing (peon).isManager(); will(returnValue(false));
        allowing (manager).isManager(); will(returnValue(true));
        
        ...
    }});
    
    ...
}
Queries should not require train-wreck expressions because that couples the object doing the selecting or sorting to the structure of the objects in the collection. The following code is a bit dodgy. The train-wreck expression will make code difficult to test with mock objects because a test will need to create a mock for each link in the chained expression.
Person findAManager(List employees) {
    List managers = new List();
    for (Employee employee : employees) {
        if (employee.getJobDescription().getRoles().contains(Role.MANAGER)) {
            managers.add(employee);
        }
    }
    return managers;
}
Introducing an isManager method on the Employee class makes testing easier and express the intent of the code more clearly.

12 October 2006

An unsung benefit of Tell, Don't Ask

The Tell Don't Ask programming style forces you to represent and name interactions between objects. This is a great help during maintenance. The code better expresses what it is doing, not just how it is doing it. The following code promotes an employee to be manager of their department:
employee.getJobDescription().getResponsibilities().add(new ManagementResponsibility(employee.getDepartment()));
But a Tell Don't Ask style forces us to state that explicitly:
employee.promoteToManager();

11 October 2006

How do you mock casts?

An occasional question that comes up on the jMock users' mailing list is how to mock casts? This is, I guess, mostly needed when interfaces are used to define capabilities of an object that are dynamically discovered by some other object in the system, somewhat like this:
public class Juicer {
    public void juice(Juiceable fruit) {
        if (fruit instanceof Peelable) ((Peelable)fruit).peel();
        fruit.juice();
    }
}
If you create a mock Juiceable object when testing the Juicer, how can you create an expectation for the cast to Peelable and make it return a mock Peelable? Casts and the instanceof operator are implemented at the language/VM level and cannot be mocked out. However, you don't need to mock them at all . You can instead define an interface in your test that can be cast to the required interface and mock that.
public class JuicerTest extends MockObjectTestCase {
    interface PeelableAndJuiceable implements Peelable, Juiceable {}

    public void testPeelsPeelableFruitBeforeJuicing() {
        PeelableAndJuiceable fruit = mock(PeelableAndJuiceable.class, "fruit");
        Juicer juicer = new Juicer();

        expects(new InThisOrder() {{
            exactly(1).of (fruit).peel();
            exactly(1).of (fruit).juice();
        }});

        juicer.juice(fruit);
    }
}
David Saff makes a good point: "[You might] find that the new interface captures a new abstraction in your code that is useful in other places. In my experience, if it's worth testing, it's often worth naming."

10 October 2006

Tell Don't Ask and Mock Objects

In my experience, object-oriented code is easier to understand and maintain if it is written in a "Tell, Don't Ask" style. In this style, objects make decisions using only the information that they hold internally or that they receive as message parameters; they do not make decisions using information that is held by other objects. That is, objects tell each other what to do by sending commands to one another, they don't ask each other for information and then make decisions upon the results of those queries. The end result of this style is that it is easy to swap one object for another that can respond to the same commands but in a different way. This is because the behaviour of one object is not tied to the internal structure of the objects that it talks to. How does that apply to Mock Objects? If objects interact by sending each other commands, their public interfaces provide no methods that let you interrogate their state. The only way to observe the behaviour of an object is to see how it affects the state of its world by sending commands to other objects. And that's what Mock Objects let you do. The extreme opposite of the "Tell, Don't Ask" style is "train-wreck" code that contains lots of statements like "object.getPart().getSubpart().getAttribute()" and "object.getPart().getSubpart().setAttribute(x)". In coding style the implementation of one object is coupled to the structure of its neighbours and its neighbours' neighbours, and so it is difficult to replace its neighbour with one that is implemented differently. This style of code is hard to test with Mock Objects. You find yourself creating lots of mock objects that only exist to let the object under test reach the objects that it actually uses. That's a strong sign that the code needs refactoring: you can simplify the code by introducing new methods in the immediate neighbours of the object under test.

09 October 2006

[jMock] Keywords and values

Someone recently asked us about the jMock syntax. Why do we write: mockFoo.expects(once()).method("bar").with(eq(1)).will(returnValue(99)); rather than, say mockFoo.expects().once().method("foo") etc.. The methods expects, method, with, and will are defined on our builder interfaces and chained on the same object. On the other hand, once, eq, and returnValue are attached to the container—MockObjectTestCase. One way to think of it is that our chained methods are keywords in our Domain-Specific Language, they're the fixed part of the language. The container methods represent values, points where users of the language can write their own extensions. In jMock, all these values are either a Constraint or a Stub. We provide common implementations of these interfaces, but users can write their own to add a behaviour that is meaningful within the domain of their application.

Between not inside

A frequent question from new users on the jMock users' mailing list is how to use jMock to mock out one method of an object while testing another method of the same object. The scenario usually involves inheritance: how can one mock out a superclass method to test the subclass. A recent query had a subtle twist: the user wanted to mock out an interface method, but that interface method was implemented by a superclass and called by a subclass, as follows:
public interface I {
    public void doSomething();
}

public abstract class A implements I {
    public void doSomething() {...}
}

public class B extends A {
    public void doLotsOfStuff(){
        ...
        doSomething();
        ...
    }
}
Mock objects are a tool for designing/testing the interactions between objects. In the code above class B is calling doSomething on itself. There is no need to use mock objects to test the B class. Tests for that exercise the functionality of doLotsOfStuff should not care that it calls doSomething somewhere down the line. That's just an implementation detail.

04 October 2006

[jMock] You don't always have to repeat expectations.

Here's a question that came up at work today. One team wanted to assert in a test that the target code would call a service three times and get back a series of values. Their first thought was something like this:
thing.expects(once()).method("foo").will(returnValue(99)).id("first");
thing.expects(once()).method("foo").after("first").will(returnValue(21)).id("second");
thing.expects(once()).method("foo").after("second").will(returnValue(17));
which uses the expectation identifier to enforce sequence. A more compact version looks like this:
thing.expects(exactly(3)).method("foo")
  .will(onConsecutiveCalls(returnValue(99), returnValue(21), returnValue(17)));
This will fire each stub (returnValue()) in turn when foo() is invoked, in this case returning the series of values. Now, after the fact, I wonder if they should have stubbed the call:
thing.stubs().method("foo").will(onConsecutiveCalls(returnValue(99), returnValue(21), returnValue(17)));
It looks like the call to foo() is supporting infrastructure, not part of the specification of the behaviour of the target code. I'll have to check in the morning.

27 September 2006

Mocks driving an SRP(*) design

Earlier this month, there was an interesting discussion on the Test-Driven Development list. avinap77 was reflecting on test-driving his code using mocks. Later on, he posted this to the list.
[...] I also realized that an expectation is more than just expecting a method to be invoked - it's also the paramaters that are sent to it and what happens with the method's result. In the example, my class needed to invoke a getCustomerDetails() method on the IDatabase collabroator, send it the appropriate ID as a paramater, and then send the resulting customerName to another collaborator (the IHtmlFormatter), and finally return the formatter's result - so this is in fact testing four different operations. I also found that these "smells" turn up pretty early - as soon as I'm trying to write a test with too many interactions, that's the immediate "red light" that the class has too many responsibilities, and I immediately start writing a more focused test which introduces more focused responsibilities represented as narrow interfaces (such as replacing the IDataBase with the INameProvider in the example). This is opposed to some state-based "baby steps" examples I've seen where the splitting into responsibilities might come later during refactoring. Do you find this too when using mocks/interactions?
This is the experience we keep trying to convey when promoting Mock Objects as a technique, with limited success. It forces you to think about what the pieces should be and where they go. One of the real hurdles to working well with Mocks is to realise that the point is not to reproduce interactions with existing types, but to force the discovery of new types. (*) SRP Single Responsibility Principle

What happened to the mockobjects.com library?

We recently had an inquiry about our old mockobjects.com library. It's still in cvs at the sourceforge project but, essentially, it's dormant. These days, there are better alternatives for Java, like EasyMock and (ahem) our own jMock.

25 September 2006

Like a Fire Drill

David Saff has come up with an entertaining metaphor for using mock objects: the School Fire Drill. There are a couple of ways to test that your pupils are prepared for a fire. You can set light to the school: the alarm will go off, everyone will troop outside, and the fire brigade will turn up and douse the building in water. Now you've tested the whole system so you can be sure that everything works. Of course, you'll have also lost your job but that's another matter. Alternatively, you can coordinate with the fire station and just set off the alarm. You can check that the pupils don't rush the exits and that everyone is accounted for. You can try a couple of different assembly points without much cost. You can keep your job. The rest of the system can be tested separately: you can check the alarm on Wednesdays at 11:00, and the fire brigade will have its own drills. Every once in a while, some building really will catch fire which will confirm that things work end-to-end. (In software, of course, you can run functional tests more predictably).

23 September 2006

Normal service will be resumed.

This is a new implementation of the mockobjects.com site. We'll port the material from the old site and add new content about working with Mock Objects.