dagblog.
← Archive

A five-minute introduction to Mockito


A few people asked me about Mockito. After trying it, they agreed with me that it’s an essential tool for writing tests. I’m going to cover just the main features and add a few comments along the way. Even if you’ve never used the library, this should give you enough to handle 80% of the cases you’ll run into when testing.

One reason developers dislike writing tests is all the boilerplate they need to set up the environment around the object under test, plus the difficulty of checking the results. This is exactly where Mockito comes to the rescue.

Mockito lets you mock classes and their behavior and check how they interact with their surroundings. I don’t know of Czech equivalents for “mock” and “mocking,” and I doubt there are any. A mock is a dynamically created object with the interface of the class in question. Mocking means defining what the mock does when something interacts with it. For example, I call method X on the mock and want it to return 1.

As an aside, Mockito helped me see how hard it is to test code effectively when its object-oriented design is poor. Alongside all its features for writing tests, it exposes weaknesses in the design and makes me think about how to improve it. That, in turn, makes the code easier to test.

For a simple Mockito example I’ve picked two objects, Basket and Item, representing a shopping basket and the goods in it. The basket has methods to add an item, empty the basket, and return the total price of its contents. To keep things simple, an item has only one method, which returns its price.

public class Item {
private final double price;
public Item(double price) {
super();
this.price = price;
}
public double getPrice() {
return price;
}
}
public class Basket {
private final List items;
public Basket() {
this(new ArrayList());
}
Basket(List items) {
super();
this.items = items;
}
public Basket addItem(Item item) {
this.items.add(item);
return this;
}
public List getItems() {
return items;
}
public void clear() {
this.items.clear();
}
public double getTotalPrice() {
double totalPrice = 0;
for (Item item : items) {
totalPrice += item.getPrice();
}
return totalPrice;
}
}
The key class for using Mockito is org.mockito.Mockito. It has a lot of static methods, so a static import is handy. These are the most important methods.
  • Mockito.mock takes a class and creates a mock from it. The class must be non-final.
  • Mockito.when defines what happens when a method is called, for example whether it returns a value or throws an exception.
  • Mockito.verify checks that a particular method on the mock was called, including the arguments passed to it.
The first example tests the expected behavior of the method that totals the price of the goods in the basket. We’ll create two mock items and add them to the basket.
public void testGetTotalPrice() {
Basket basket = new Basket();
Item item1 = mock(Item.class);
when(item1.getPrice()).thenReturn(10d);
Item item2 = mock(Item.class);
when(item2.getPrice()).thenReturn(20d);
basket
.addItem(item1)
.addItem(item2);
assertThat("The total price must be sum of all prices in basket", basket.getTotalPrice(), is(30d));
}
To mock a piece of merchandise, represented by the Item class, we first created a mock and then defined the behavior of getPrice. You might argue that there’s no reason to mock Item here and that we could just use an instance. I tend to use mocks throughout because it reduces the dependencies between test classes and methods.
The next test checks that calling clear really does empty the basket. We can do that by verifying how the object interacts with its surroundings. I mocked the internal list in which the basket keeps its items, then verified that the list’s clear method was called.
@Test
public void testClear() {
List items = mock(List.class);
Basket basket = new Basket(items);
basket.clear();
verify(items).clear();
}
The last line verifies the call to clear on the mock. You can test adding goods to the basket in much the same way, by mocking the internal list. I’ll get to why this technique is a little controversial in a moment.
@Test
public void testAddItem() {
Item item = mock(Item.class);
List items = mock(List.class);
Basket basket = new Basket(items);
basket.addItem(item);
verify(items).add(item));
}
Using mocks and verifying their interactions with the object under test has several drawbacks. Once you start verifying interactions this way, you’re checking the internal implementation, something a black-box test should never care about. Think carefully about what really needs checking. A change in the implementation can make tests fail just because they were coupled to implementation details. Another drawback is that you sometimes have to break encapsulation for the tests and expose the very part you need to mock.
Mockito can do much more than the methods covered here. You can verify the arguments passed to a mock or check that there were no interactions. You can create partial mocks too. These three methods cover the basics of working with Mockito.

Medium version

Related articles

Related CZ Podcast episodes