Mocking, Stubbing and Test Spying using the Mockito Framework and PowerMock
March 27th, 2011 by Micha Kops
Today we’re going to take a look at the Mockito framework that not only does sound like my favourite summer cocktail but also offers nice testing, mocking/stubbing, test-spying features and mock injections.
After that we’re going to take a look on how to mock static or final classes by extending Mockito’s capabilities with PowerMock.
Contents
- Prerequisites
- Setup Project
- Classes under Test
- Mocking
- Stubbing
- Argument Matchers
- Test Spying / Verification
- Behaviour Driven Development / BDD Aliases
- Mocking static or final classes .. PowerMock to the rescue
- Troubleshooting / Common Mistakes
- Update: Mockito 2 and Mocking static or final classes
- Download Tutorial Sources
- Resources
- Article Updates
Prerequisites
We don’t need much for the following samples .. Java of course, Maven dependency management and that’s all ..
Setup Project
We don’t have much to do here .. we need a mavenized project and one dependency ..
- We’re creating a new Maven project using the favourite IDE with Maven support or via command line using
mvn archetype:generate
- In the next step, we’re adding the dependency for mockito-core to our pom.xml that finally looks like this
<?xml version="1.0" encoding="utf-16"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.hascode.tutorial</groupId> <artifactId>mockito-tutorial</artifactId> <version>0.0.1</version> <dependencies> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.8.5</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> </dependencies> </project>
Classes under Test
Before we’re starting to write our tests we need some classes to be tested and mocked.. they’re all created in src/main/java in the package com.hascode.tutorial.
UserBean
package com.hascode.tutorial; import java.util.Calendar; public interface UserBean { String getName(); String setName(); Calendar getLastLogin(); void setLastLogin(Calendar lastLogin); boolean isActive(); void setActive(boolean active); }
UserRepository
package com.hascode.tutorial; import java.util.List; public interface UserRepository { List<UserBean> findAll(); void save(final UserBean user); void remove(final UserBean user); }
NotificationService
package com.hascode.tutorial; public interface NotificationService { void notifyUser(final UserBean user, final String message); }
AccountService
package com.hascode.tutorial; public class AccountService { private final UserRepository userRepository; private final NotificationService notificationService; public AccountService(final UserRepository userRepository, final NotificationService notificationService) { this.userRepository = userRepository; this.notificationService = notificationService; } public void removeUser(final UserBean user) { notificationService.notifyUser(user, getUserDeletionMessage(user)); userRepository.remove(user); } private String getUserDeletionMessage(final UserBean user) { return String.format("Dear administrator,\n the following user account has been deleted: %s", user.getName()); } }
Mocking
Mockito is not able to mock static or final classes – I’ll show you how to do this by combining Mockito and PowerMock in the last chapter. For all other stuff we’re able to create mocks using Mockito.mock or – my favourite – annotations and mock injection.
Using static imports might improve the readability of your tests but some programmers dont’t like them .. so it’s your choice .. I only like them in my tests ;)
- First a simple mock example mocking the UserRepository
package com.hascode.tutorial; import static org.mockito.Mockito.mock; import org.junit.Test; public class SimpleMockExample { @Test public void testSomething() { UserRepository userRepository = mock(UserRepository.class); } }
- Now using mock injection and annotations – the more mocks are used in a test the more you’re going to like this version
package com.hascode.tutorial; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class SimpleMockExampleWithAnnotations { @Mock private UserRepository userRepository; @Before public void setUp() { MockitoAnnotations.initMocks(this); } @Test public void testSomething() { // ... } }
- Since version 1.8 a mock can be resetted using reset(mock) – or in our example reset(userRepository);. More details on this in the section about verification..
- Another nice feature (since 1.8) is the @InjectMocks annotation that allows setter injection for mocked dependencies but be aware you need to call MockitoAnnotations.initMocks() to make it work.
Stubbing
Now that we’re able to create mocks the next step is to stub some method calls ..
- Stubbing is really easy .. using the following syntax when(mock.method()).thenReturn(..)
- In addition it is possible to stub void methods to throw an exception using doThrow(new Exception()).when(mock).method(); The following example mocks the findAll method and returns null and forces the save method to throw a RuntimeException
package com.hascode.tutorial; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import junit.framework.Assert; import org.junit.Test; public class SimpleStubExample { @Test(expected = RuntimeException.class) public void testSomething() { UserRepository userRepository = mock(UserRepository.class); when(userRepository.findAll()).thenReturn(null); doThrow(new RuntimeException()).when(userRepository).save(any(UserBean.class)); Assert.assertNull(userRepository.findAll()); userRepository.save(null); } }
- Please note that I have used Mockito’s argument matcher API here and that leads to the following chapter – Argument Matchers :)
Argument Matchers
Mockito offers a variety of argument matchers for flexible verification or stubbing – often used matchers are these:
- any() / any(Class<T> clazz): matches any object - the class argument is provided only to avoid casting
- anyBoolean(): matches any boolean value or null
- anyByte(): matches any byte or null
- anyChar(): matches any char or null
- anyCollection() / anyCollectionOf(Class<T> clazz): matches any collection (or generic collection) or null
- anyDouble(): matches any double or null
- anyFloat(): matches any float or null
- anyInt(): matches any integer or null
- anyList() / anyListOf(Class<T> clazz): matches any list (or generic list) or null
- anyMap(): matches any map or null
- anySet / anySetOf(Class<T> clazz): matches any set (or generic set) or null
- anyString: matches any string or null
- and many others .. for a complete list of available matchers and providing custom extensions to the matcher API take a look at the Matcher javadocs.
Please be aware that if you’re using argument matchers, all arguments in verify or stub must be provided by matchers.
Test Spying / Verification
Mockito’s test spy features allow the developer to take a look behind the curtain and verify how often, in which order and how long invocations on a mock object’s method have been triggered.
Verification enables you to test the behaviour of methods with void return but you shouldn’t overuse this feature .. use JUnit’s Assert methods when possible, verify when needed.. more about this topic from the creator of Mockito: Szepan Faber: Is there a difference between asking and telling?
These are our verification methods:
- Verify that a method has been called at least once: verify(mock).method() or verify(mock, times(1)).method()
- Verify an exact number of incovations: verify(mock, times(number)).method()
- Verify that a method has never been called: verify(mock, never()).method() or verify(mock, times(0)).method()
- Verify that a method has been called at least n times: verify(mock, atLeast(n)).method()
- Verify that a method has been called at most n times: verify(mock, atMost(n)).method()
- Take a look at the following example
package com.hascode.tutorial; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.junit.Test; public class VerificationExample { @Test public void testExample() { // mock NotificationService notificationService = mock(NotificationService.class); UserRepository userRepository = mock(UserRepository.class); UserBean user = mock(UserBean.class); // init AccountService service = new AccountService(userRepository, notificationService); // run service.removeUser(user); // verify verify(notificationService, times(1)).notifyUser(any(UserBean.class), anyString()); // verify // 1 // invocation verify(userRepository).remove(any(UserBean.class)); // verify 1 // invocation, short // syntax reset(notificationService); // reset the mocks reset(userRepository); verify(notificationService, never()).notifyUser(any(UserBean.class), anyString()); service.removeUser(user); service.removeUser(user); verify(notificationService, times(2)).notifyUser(any(UserBean.class), anyString()); verify(userRepository, atLeast(2)).remove(any(UserBean.class)); } }
Behaviour Driven Development / BDD Aliases
Since version 1.8.0 Mockito supports aliases for the friends of Behaviour Driven Development – those are only aliases and do not mean that your tests fulfil the BDD paradigm just because there’s a given-when-then syntax :)
- The alias for the stub method is given – a full overview of the aliases can be found in the the javadocs for BDDMockito
- If you’re going to take a deeper look into BDD please take a look at the following article of mine about BDD and the JBehave framework.
Mocking static or final classes .. PowerMock to the rescue
Often a developer gets into the situation to mock final or static classes from third-party libraries or legacy code. Mockito alone is not able to mock static or final classes .. we could – of course write utility classes using the reflection API or – just take a look at the PowerMock framework.
Mocking static classes/methods is really easy and is achieved passing the following steps:
- Add the dependency for the PowerMock Mockito integration to your pom.xml
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-mockito-release-full</artifactId> <version>1.4.8</version> <type>pom</type> <scope>test</scope> </dependency>
- Run your unit test with @RunWith(PowerMockRunner.class)
- Prepare the static class to be mocked using @PrepareForTest(Static.class) at class level
- Call PowerMockito.mockStatic(Static.class) to mock the static class
- In the following example we’re going to mock the static method max from Java’s Math class. We’re manipulating the max method to return the lower value instead of the higher value :)
- The full test looks like this
package com.hascode.tutorial; import static org.mockito.Mockito.when; import junit.framework.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(Math.class) public class StaticClassExample { @Test public void testMockStatic() { PowerMockito.mockStatic(Math.class); when(Math.max(1, 5)).thenReturn(1); // this is soo wrong ;) Assert.assertEquals(1, Math.max(1, 5)); } }
Troubleshooting / Common Mistakes
- “org.mockito.exceptions.base.MockitoException: Cannot mock/spy class java.lang.StringBuffer Mockito cannot mock/spy following: – final classes – anonymous classes – primitive types” -> You can’t mock final or static classes (without using PowerMock)
- You can’t mix matchers with other non-matcher arguments in verification or stub methods
Update: Mockito 2 and Mocking static or final classes
With Mockito 2 it’s possible to mock static or final classes without using external tools like PowerMock.
Follow these simple steps to upgrade to Mockito 2 and activate mocking final and static classes via the plugin SPI:
1) Upgrade to Mockito 2 by adding the following dependency to your pom.xml:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.10.0</version> <scope>test</scope> </dependency>
2) Create a file named org.mockito.plugins.MockMaker in the directory src/test/resources/mockito-extensions/
3) Add the following content to this file: mock-maker-inline
Now mocking final or static classes should not be a problem.
Download Tutorial Sources
The tutorial’s source are available for download at Bitbucket.org or – if Mercurial is installed just do
hg clone https://hascode@bitbucket.org/hascode/hascode-tutorials
Resources
- Mockito Project Site
- Mockito Documentation
- PowerMock Website
- PowerMock Documentation: Using PowerMock with Mockito
- PowerMock Documentation: Mocking final classes
- PowerMock Documentation: Mocking static classes
- ICE09: Mocking and Stubbing with Mockito
- Brett L. Schuchert: Mockito.LoginServiceExample
- Jacek Furmankiewicz. Mockito: Java Unit Testing with Mock Objects
- Szepan Faber: Is there a difference between asking and telling?
- Mockito Website: Mockito vs EasyMock
- JMock Project Site
- Martin Fowler. Should I be a classicist or a mockist?
- BDD Mockito Javadocs
Article Updates
- 2017-10-03: Examples for mocking static or final classes with Mockito 2 added.
- 2015-03-21: Formatting optimized.
Tags: bdd, easymock, hamcrest, jmock, junit, mock, mock injection, mocking, mockito, powermock, stub, stubbing, tdd, testing, unit test
January 8th, 2012 at 10:44 pm
regarding matchers, I think what you say is slightly misleading, e.g.
any() / any(Class clazz): matches any object (or object of a given class) or null
according to Mockito javadocs (http://docs.mockito.googlecode.com/hg/org/mockito/Matchers.html):
any(java.lang.Class clazz) any kind object, not necessary of the given class. The class argument is provided only to avoid casting.
January 9th, 2012 at 2:10 pm
you’re right! thanks for mentioning! :)