Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / testing

Mocking Frameworks vs Unit Testing Style

0.00/5 (No votes)
19 Jan 2015CPOL1 min read 5.5K  
Mocking frameworks vs Unit Testing style

I've never paid much attention to what mocking framework I use. I've used EasyMock and JMock, I observed no big difference between the two really. Recently, I started to change some existing JMock unit tests to use Mockito instead. It seemed to have a more elegant interface, and it turned out this had other implications on my tests than mere syntactic sugar. It actually gave some new insight on the subject.

A little toy code to illustrate this:

Java
public interface GreetingFormula {
 String formula();
}

public class Greeting {
 private GreetingFormula gf;

 public Greeting(GreetingFormula gf) {
  this.gf = gf;
 }

 public String greet(String name) {
  return gf.formula() + " " + name;
 }
}

In my Unit Test for Greeting, I want a Mock object for the GreetingFormula interface. I want to verify that formula() has been actually called on the Mock object, and also want some return value for the method. A JMock implementation would look like this:

Java
public class GreetingTest {
 private final static String formulaText = "Hello";
 private final static String name = "Mr. Doe"
 private final static String expectedGreeting = "Hello Mr. Doe";

 private Mockery mockingContext;
 private GreetingFormula greetingFormula;
 private Greeting greeting;
 
 @Test
 public void greetPutsNameIntoFormula() {
  mockingContext.checking(new Expectations() {
   {
    one(greetingFormula).formula();
    will(returnValue(formulaText));
   }
  });
  Assert.assertEquals(expectedGreeting, greeting.greet());     
 }

 @Before
 public void setUp() {
  mockingContext = new JUnit4Mockery();
  greetingFormula = mockingContext.mock(GreetingFormula.class);
  greeting = new Greeting(greetingFormula);    
 }
}

The solution may look ok at first glance, but there is a subtle issue here. In expectations, two very different concepts are mixed together: how the mock object should behave (return the right value), and what should be verified on the mock object afterwards (it has been called exactly once). Let's take a look at how the same task is done using Mockito.

Java
public class GreetingTest {
 private final static String formulaText = "Hello";
 private final static String name = "Mr. Doe"
 private final static String expectedGreeting = "Hello Mr. Doe";

 private GreetingFormula greetingFormula;
 private Greeting greeting;
 
 @Test
 public void greetPutsNameToFormula() {
  when(greetingFormula.formula()).thenReturn(formulaText);
  assertEquals(expectedGreeting, greeting.greet());
  verify(greetingFormula).formula();     
 }

 @Before
 public void setUp() {
  greetingFormula = mock(GreetingFormula.class);
  greeting = new Greeting(greetingFormula);    
 }
}

Mockito enforces the clear separation of the concepts of mock object behavior and verification by its design, there is simply no other way of doing it. This might not look like a big deal - on a simple example like this - but in fact it is. Unit test code with a lot of mockery does gain a lot of clarity simply by expressing these steps in the right order:

  • Mock behaviour
  • Perform test
  • Mock verification

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)