Mocking, Stubbing and Test Spying using the Mockito Framework and PowerMock

March 27th, 2011 by


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.


 

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

Article Updates

  • 2017-10-03: Examples for mocking static or final classes with Mockito 2 added.
  • 2015-03-21: Formatting optimized.

Tags: , , , , , , , , , , , , , ,

2 Responses to “Mocking, Stubbing and Test Spying using the Mockito Framework and PowerMock”

  1. Tomek Kaczanowski Says:

    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.

  2. micha kops Says:

    you’re right! thanks for mentioning! :)

Search
Tags
Categories