Unit testing has become mandatory in the age of Agile, and there are many tools available to help with automated testing. One such tool is Mockito, an open source framework that lets you create and configure mocked objects for tests.

In this article, we’ll cover creating and configuring mocks and using them to verify the expected behavior of the system being tested. We’ll also dive a bit into Mockito’s internals to better understand its design and caveats. We’ll be using JUnit as a unit testing framework, but since Mockito is not bound to JUnit, you can follow along even if you’re using a different framework.

Obtaining Mockito

Getting Mockito is easy these days. If you’re using Gradle, it’s a matter of adding this single line to your build script:

testCompile "org.mockito:mockito−core:2.7.7"

As for those like me who still prefer Maven, just add Mockito to your dependencies like so:

<dependency> 
    <groupId>org.mockito</groupId> 
    <artifactId>mockito-core</artifactId> 
    <version>2.7.7</version> 
    <scope>test</scope> 
</dependency>

Of course, the world is much wider than Maven and Gradle. You’re free to use any project management tool to fetch the Mockito jar artifact from the Maven central repository.

Approaching Mockito

Unit tests are designed to test the behavior of specific classes or methods without relying on the behavior of their dependencies. Since we’re testing the smallest ‘unit’ of code, we don’t need to use actual implementations of these dependencies. Furthermore, we’ll use slightly different implementations of these dependencies when testing different behaviors. A traditional, well-known approach to this is to create ‘stubs’– specific implementations of an interface suitable for a given scenario. Such implementations usually have hard-coded logic. A stub is a kind of test double. Other kinds include fakes, mocks, spies, dummies, etc.

We’ll be focusing only on two types of test doubles, ‘mocks’ and ‘spies’, as these are heavily employed by Mockito.

Mocks

What is mocking? Obviously, it’s not where you make fun of your fellow developers. Mocking for unit testing is when you create an object that implements the behavior of a real subsystem in controlled ways. In short, mocks are used as a replacement for a dependency.

With Mockito, you create a mock, tell Mockito what to do when specific methods are called on it, and then use the mock instance in your test instead of the real thing. After the test, you can query the mock to see what specific methods were called or check the side effects in the form of changed state.

By default, Mockito provides an implementation for every method of the mock.

Spies

A spy is the other type of test double that Mockito creates. In contrast to mocks, creating a spy requires an instance to spy on. By default, a spy delegates all method calls to the real object and records what method was called and with what parameters. That’s what makes it a spy: It’s spying on a real object.

Consider using mocks instead of spies whenever possible. Spies might be useful for testing legacy code that can’t be redesigned to be easily testable, but the need to use a spy to partially mock a class is an indicator that a class is doing too much, thus violating the single responsibility principle.

Building a Simple Example

Let’s have a look at a simple demo for which we can write tests. Suppose we have a UserRepository interface with a single method to find a user by its identifier. We also have the concept of a password encoder to turn a clear-text password into a password hash. Both UserRepository and PasswordEncoder are dependencies (also called collaborators) of UserService injected via the constructor. Here’s what our demo code looks like:

UserRepository
public interface UserRepository {
   User findById(String id);
}
User
public class User {

   private String id;
   private String passwordHash;
   private boolean enabled;

   public User(String id, String passwordHash, boolean enabled) {
       this.id = id;
       this.passwordHash = passwordHash;
       this.enabled = enabled;
   }
   ...
}
PasswordEncoder
public interface PasswordEncoder {
   String encode(String password);
}
UserService
public class UserService {

   private final UserRepository userRepository;
   private final PasswordEncoder passwordEncoder;

   public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
       this.userRepository = userRepository;
       this.passwordEncoder = passwordEncoder;
   }

   public boolean isValidUser(String id, String password) {
       User user = userRepository.findById(id);
       return isEnabledUser(user) && isValidPassword(user, password);
   }

   private boolean isEnabledUser(User user) {
       return user != null && user.isEnabled();
   }

   private boolean isValidPassword(User user, String password) {
       String encodedPassword = passwordEncoder.encode(password);
       return encodedPassword.equals(user.getPasswordHash());
   }
}

This example code can be found on GitHub, so you can download it for review alongside this article.

Applying Mockito

Using our example code, let’s look at how to apply Mockito and write some tests.

Creating Mocks

With Mockito, creating a mock is as easy as calling a static method Mockito.mock():

import static org.mockito.Mockito.*;
...
PasswordEncoder passwordEncoder = mock(PasswordEncoder.class);

Notice the static import for Mockito. For the rest of this article, we’ll implicitly consider this import added.

After the import, we mock out PasswordEncoder, an interface. Mockito mocks not only interfaces but also abstract classes and concrete non-final classes. Out of the box, Mockito cannot mock final classes and final or static methods, but if you really need it, Mockito 2 provides the experimental MockMaker plugin.

Also note that the methods equals() and hashCode() cannot be mocked.

Creating Spies

To create a spy, you need to call Mockito’s static method spy() and pass it an instance to spy on. Calling methods of the returned object will call real methods unless those methods are stubbed. These calls are recorded and the facts of these calls can be verified (see further description of verify()). Let’s make a spy:

DecimalFormat decimalFormat = spy(new DecimalFormat());
assertEquals("42", decimalFormat.format(42L));

Creating a spy does not differ much from creating a mock. Moreover, all Mockito methods used for configuring a mock are also applicable to configuring a spy.

Spies are rarely used compared to mocks, but you may find them useful for testing legacy code that cannot be refactored, where testing it requires partial mocking. In those cases, you can just create a spy and stub some of its methods to get the behavior you want.

Default Return Values

Calling mock(PasswordEncoder.class) returns an instance of PasswordEncoder. We can even call its methods, but what will they return? By default, all methods of a mock return “uninitialized” or “empty” values, e.g., zeros for numeric types (both primitive and boxed), false for booleans, and nulls for most other types.

Consider the following interface:

interface Demo {
   int getInt();
   Integer getInteger();
   double getDouble();
   boolean getBoolean();
   String getObject();
   Collection<String> getCollection();
   String[] getArray();
   Stream<?> getStream();
   Optional<?> getOptional();
}

Now consider the following snippet, which gives an idea of what default values to expect from the methods of a mock:

Demo demo = mock(Demo.class);
assertEquals(0, demo.getInt());
assertEquals(0, demo.getInteger().intValue());
assertEquals(0d, demo.getDouble(), 0d);
assertFalse(demo.getBoolean());
assertNull(demo.getObject());
assertEquals(Collections.emptyList(), demo.getCollection());
assertNull(demo.getArray());
assertEquals(0L, demo.getStream().count());
assertFalse(demo.getOptional().isPresent());

Stubbing Methods

Fresh, unaltered mocks are useful only in rare cases. Usually, we want to configure the mock and define what to do when specific methods of the mock are called. This is called stubbing.

Mockito offers two ways of stubbing. The first way is “when this method is called, then do something.” Consider the following snippet:

when(passwordEncoder.encode("1")).thenReturn("a");

It reads almost like English: “When passwordEncoder.encode(“1”) is called, return an a.”

The second way of stubbing reads more like “Do something when this mock’s method is called with the following arguments.” This way of stubbing is harder to read as the cause is specified at the end. Consider:

doReturn("a").when(passwordEncoder).encode("1");

The snippet with this method of stubbing would read: “Return a when passwordEncoder’s encode() method is called with an argument of 1.”

The first way is considered preferred because it is typesafe and because it’s more readable. Rarely, however, you’re forced to use the second way, such as when stubbing a real method of a spy because calling it may have unwanted side effects.

Let’s briefly explore the stubbing methods provided by Mockito. We’ll include both ways of stubbing in our examples.

Returning Values

thenReturn or doReturn() are used to specify a value to be returned upon method invocation.

//”when this method is called, then do something”
when(passwordEncoder.encode("1")).thenReturn("a");

or

//”do something when this mock’s method is called with the following arguments”
doReturn("a").when(passwordEncoder).encode("1");

You can also specify multiple values which will be returned as the results of consecutive method calls. The last value will be used as a result for all further method calls.

//when
when(passwordEncoder.encode("1")).thenReturn("a", "b");

or

//do
doReturn("a", "b").when(passwordEncoder).encode("1");

The same can be achieved with the following snippet:

when(passwordEncoder.encode("1"))
       .thenReturn("a")
       .thenReturn("b");

This pattern can also be used with other stubbing methods to define the results of consecutive calls.

Returning Custom Responses

then(), an alias to thenAnswer(), and doAnswer() achieve the same thing, which is set up a custom answer to be returned when a method is called, like so:

when(passwordEncoder.encode("1")).thenAnswer(
       invocation -> invocation.getArgument(0) + "!");

or

doAnswer(invocation -> invocation.getArgument(0) + "!")
       .when(passwordEncoder).encode("1");

The only argument thenAnswer() takes is an implementation of the Answer interface. It has a single method with a parameter of type InvocationOnMock.

You can also throw an exception as a result of a method call:

when(passwordEncoder.encode("1")).thenAnswer(invocation -> {
   throw new IllegalArgumentException();
});

…or call the real method of a class (not applicable to interfaces):

Date mock = mock(Date.class);
doAnswer(InvocationOnMock::callRealMethod).when(mock).setTime(42);
doAnswer(InvocationOnMock::callRealMethod).when(mock).getTime();
mock.setTime(42);
assertEquals(42, mock.getTime());

You’re right if you think that it looks cumbersome. Mockito provides thenCallRealMethod() and thenThrow() to streamline this aspect of your testing.

Calling Real Methods

As its name suggests, thenCallRealMethod() and doCallRealMethod() call the real method on a mock object:

Date mock = mock(Date.class);
when(mock.getTime()).thenCallRealMethod();
doCallRealMethod().when(mock).setTime(42);
mock.setTime(42);
assertEquals(42, mock.getTime());

Calling real methods may be useful on partial mocks, but make sure that the called method has no unwanted side effects and doesn’t depend on object state. If it does, a spy may be a better fit than a mock.

If you create a mock of an interface and try to configure a stub to call a real method, Mockito will throw an exception with very informative message. Consider the following snippet:

when(passwordEncoder.encode("1")).thenCallRealMethod();

Mockito will fail with the following message:

Cannot call abstract real method on java object!
Calling real methods is only possible when mocking non abstract method.
  //correct example:
  when(mockOfConcreteClass.nonAbstractMethod()).thenCallRealMethod();

Kudos to the Mockito developers for caring enough to provide such thorough descriptions!

Throwing Exceptions

thenThrow() and doThrow() configure a mocked method to throw an exception:

when(passwordEncoder.encode("1")).thenThrow(new IllegalArgumentException());

or

doThrow(new IllegalArgumentException()).when(passwordEncoder).encode("1");

Mockito ensures that the exception being thrown is valid for that specific stubbed method and will complain if the exception is not in the method’s checked exceptions list. Consider the following:

when(passwordEncoder.encode("1")).thenThrow(new IOException());

It will lead to an error:

org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: java.io.IOException

As you can see, Mockito detected that encode() can’t throw an IOException.

You can also pass an exception’s class instead of passing an instance of an exception:

when(passwordEncoder.encode("1")).thenThrow(IllegalArgumentException.class);

or

doThrow(IllegalArgumentException.class).when(passwordEncoder).encode("1");

That said, Mockito cannot validate an exception class in the same way as it will validate an exception instance, so you must be disciplined and not pass illegal class objects. For example, the following will throw IOException though encode() is not expected to throw a checked exception:

when(passwordEncoder.encode("1")).thenThrow(IOException.class);
passwordEncoder.encode("1");

Mocking Interfaces with Default Methods

It’s worth noting that when creating a mock for an interface, Mockito mocks all the methods of that interface. Since Java 8, interfaces may contain default methods along with abstract ones. These methods are also mocked, so you need to take care to make them act as default methods.

Consider the following example:

interface AnInterface {
   default boolean isTrue() {
       return true;
   }
}
AnInterface mock = mock(AnInterface.class);
assertFalse(mock.isTrue());

In this example, assertFalse() will succeed. If that’s not what you expected, make sure that you’ve had Mockito call the real method, like so:

AnInterface mock = mock(AnInterface.class);
when(mock.isTrue()).thenCallRealMethod();
assertTrue(mock.isTrue());

Argument Matchers

In the previous sections, we configured our mocked methods with exact values as arguments. In those cases, Mockito just calls equals() internally to check if the expected values are equal to the actual values.

Sometimes, though, we don’t know these values beforehand.

Maybe we just don’t care about the actual value being passed as an argument, or maybe we want to define a reaction for a wider range of values. All these scenarios (and more) can be addressed with argument matchers. The idea is simple: Instead of providing an exact value, you provide an argument matcher for Mockito to match method arguments against.

Consider the following snippet:

when(passwordEncoder.encode(anyString())).thenReturn("exact");
assertEquals("exact", passwordEncoder.encode("1"));
assertEquals("exact", passwordEncoder.encode("abc"));

You can see that the result is the same no matter what value we pass to encode() because we used the anyString() argument matcher in that first line. If we rewrite that line in plain English, it would sound like “when the password encoder is asked to encode any string, then return the string ‘exact.’”

Mockito requires you to provide all arguments either by matchers or by exact values. So if a method has more than one argument and you want to use argument matchers for only some of its arguments, forget it. You can’t write code like this:

abstract class AClass {
   public abstract boolean call(String s, int i);
}
AClass mock = mock(AClass.class);
//This doesn’t work.
when(mock.call("a", anyInt())).thenReturn(true);

To fix the error we must replace the last line to include the eq argument matcher for a, as follows:

when(mock.call(eq("a"), anyInt())).thenReturn(true);

Here we’ve used the eq() and anyInt() argument matchers, but there are many others available. For a full list of argument matchers refer to the documentation on the org.mockito.ArgumentMatchers class.

It’s important to note that you cannot use argument matchers outside of verification or stubbing. For example, you can’t have the following:

//this won’t work
String orMatcher = or(eq("a"), endsWith("b"));
verify(mock).encode(orMatcher);

Mockito will detect the misplaced argument matcher and throw an InvalidUseOfMatchersException. Verification with argument matchers should be done this way:

verify(mock).encode(or(eq("a"), endsWith("b")));

Argument matchers cannot be used as return value, either. Mockito can’t return anyString() or any-whatever; an exact value is required when stubbing calls.

Custom Matchers

Custom matchers come to the rescue when you need to provide some matching logic that is not already available in Mockito. The decision to create a custom matcher shouldn’t be taken lightly since the need to match arguments in a non-trivial way indicates either a problem in design or that a test is getting too complicated.

As such, it’s worth checking whether you can simplify a test by using some of the lenient argument matchers such as isNull() and nullable() before writing a custom matcher. If you still feel the need to write an argument matcher, Mockito provides a family of methods to do it.

Consider the following example:

FileFilter fileFilter = mock(FileFilter.class);
ArgumentMatcher<File> hasLuck = file -> file.getName().endsWith("luck");
when(fileFilter.accept(argThat(hasLuck))).thenReturn(true);
assertFalse(fileFilter.accept(new File("/deserve")));
assertTrue(fileFilter.accept(new File("/deserve/luck")));

Here we create the hasLuck argument matcher and use argThat() to pass the matcher as an argument to a mocked method, stubbing it to return true if the filename ends with “luck.” You can treat ArgumentMatcher as a functional interface and create its instance with a lambda (which is what we’ve done in the example). Less concise syntax would look like:

ArgumentMatcher<File> hasLuck = new ArgumentMatcher<File>() {
   @Override
   public boolean matches(File file) {
       return file.getName().endsWith("luck");
   }
};

If you need to create an argument matcher that works with primitive types, there are several other methods for that in org.mockito.ArgumentMatchers:

  • charThat(ArgumentMatcher<Character> matcher)
  • booleanThat(ArgumentMatcher<Boolean> matcher)
  • byteThat(ArgumentMatcher<Byte> matcher)
  • shortThat(ArgumentMatcher<Short> matcher)
  • intThat(ArgumentMatcher<Integer> matcher)
  • longThat(ArgumentMatcher<Long> matcher)
  • floatThat(ArgumentMatcher<Float> matcher)
  • doubleThat(ArgumentMatcher<Double> matcher)

Combining Matchers

It’s not always worth creating a custom argument matcher when a condition is too complicated to be handled with basic matchers; sometimes combining matchers will do the trick. Mockito provides argument matchers to implement common logical operations (‘not’, ‘and’, ‘or’) on argument matchers that match both primitive and non-primitive types. These matchers are implemented as static methods in the org.mockito.AdditionalMatchers class.

Consider the following example:

when(passwordEncoder.encode(or(eq("1"), contains("a")))).thenReturn("ok");
assertEquals("ok", passwordEncoder.encode("1"));
assertEquals("ok", passwordEncoder.encode("123abc"));
assertNull(passwordEncoder.encode("123"));

Here we’ve combined results of two argument matchers: eq("1") and contains("a"). The final expression, or(eq("1"), contains("a")), may be interpreted as “the argument string must be equal to “1” or contain “a”.

Note that there are less common matchers listed on the org.mockito.AdditionalMatchers class, such as geq(), leq(), gt() and lt(), which are value comparisons applicable for primitive values and instances of java.lang.Comparable.

Verifying Behavior

Once a mock or spy has been used, we can verify that specific interactions took place. Literally, we are saying “Hey, Mockito, make sure this method was called with these arguments.”

Consider the following artificial example:

PasswordEncoder passwordEncoder = mock(PasswordEncoder.class);
when(passwordEncoder.encode("a")).thenReturn("1");
passwordEncoder.encode("a");
verify(passwordEncoder).encode("a");

Here we’ve set up a mock and called its encode() method. The last line verifies that the mock’s encode() method was called with the specific argument value a. Please note that verifying a stubbed invocation is redundant; the purpose of the previous snippet is to show the idea of doing verification after some interactions happened.

If we change the last line to have a different argument—say, b—the previous test will fail and Mockito will complain that the actual invocation has different arguments (b instead of the expected a).

Argument matchers can be used for verification just like for stubbing:

verify(passwordEncoder).encode(anyString());

By default, Mockito verifies that the method was called once, but you can verify any number of invocations:

// verify the exact number of invocations
verify(passwordEncoder, times(42)).encode(anyString());

// verify that there was at least one invocation
verify(passwordEncoder, atLeastOnce()).encode(anyString());

// verify that there were at least five invocations
verify(passwordEncoder, atLeast(5)).encode(anyString());

// verify the maximum number of invocations
verify(passwordEncoder, atMost(5)).encode(anyString());

// verify that it was the only invocation and
// that there're no more unverified interactions
verify(passwordEncoder, only()).encode(anyString());

// verify that there were no invocations
verify(passwordEncoder, never()).encode(anyString());

A rarely used feature of verify() is its ability to fail on a timeout, which is mainly useful for testing concurrent code. For example, if our password encoder is called in another thread concurrently with verify(), we can write a test as follows:

usePasswordEncoderInOtherThread();
verify(passwordEncoder, timeout(500)).encode("a");

This test will succeed if encode() is called and finished within 500 milliseconds or less. If you need to wait the full period you specify, use after() instead of timeout():

verify(passwordEncoder, after(500)).encode("a");

Other verification modes (times(), atLeast(), etc) can be combined with timeout() and after() to make more complicated tests:

// passes as soon as encode() has been called 3 times within 500 ms
verify(passwordEncoder, timeout(500).times(3)).encode("a");

Besides times(), supported verification modes include only(), atLeast() and atLeastOnce() (as an alias to atLeast(1)).

Mockito also allows you to verify the call order in a group of mocks. It’s not a feature to be used very often, but it may be useful if the order of invocations is important. Consider the following example:

PasswordEncoder first = mock(PasswordEncoder.class);
PasswordEncoder second = mock(PasswordEncoder.class);
// simulate calls
first.encode("f1");
second.encode("s1");
first.encode("f2");
// verify call order
InOrder inOrder = inOrder(first, second);
inOrder.verify(first).encode("f1");
inOrder.verify(second).encode("s1");
inOrder.verify(first).encode("f2");

If we rearrange the order of the simulated calls, the test will fail with VerificationInOrderFailure.

The absence of invocations can also be verified using verifyZeroInteractions(). This method accepts a mock or mocks as an argument and will fail if any methods of the passed in mock(s) were called.

It’s also worth mentioning the verifyNoMoreInteractions() method, as it takes mocks as an argument and can be used to check that every call on those mocks was verified.

Capturing Arguments

Besides verifying that a method was called with specific arguments, Mockito allows you to capture those arguments so that you can later run custom assertions on them. In other words, you’re saying “Hey, Mockito, verify that this method was called, and give me the argument values it was called with.”

Let’s create a mock of PasswordEncoder, call encode(), capture the argument, and check its value:

PasswordEncoder passwordEncoder = mock(PasswordEncoder.class);
passwordEncoder.encode("password");
ArgumentCaptor<String> passwordCaptor = ArgumentCaptor.forClass(String.class);
verify(passwordEncoder).encode(passwordCaptor.capture());
assertEquals("password", passwordCaptor.getValue());

As you can see, we pass passwordCaptor.capture() as an argument of encode() for verification; this internally creates an argument matcher that saves the argument. Then we retrieve the captured value with passwordCaptor.getValue() and inspect it with assertEquals().

If we need to capture an argument across multiple calls, ArgumentCaptor lets you retrieve all values with getAllValues(), like so:

PasswordEncoder passwordEncoder = mock(PasswordEncoder.class);
passwordEncoder.encode("password1");
passwordEncoder.encode("password2");
passwordEncoder.encode("password3");
ArgumentCaptor<String> passwordCaptor = ArgumentCaptor.forClass(String.class);
verify(passwordEncoder, times(3)).encode(passwordCaptor.capture());
assertEquals(Arrays.asList("password1", "password2", "password3"),
             passwordCaptor.getAllValues());

The same technique can be used for capturing variable arity method arguments (also known as varargs).

Testing Our Simple Example

Now that we know a lot more about Mockito, it’s time to get back to our demo. Let’s write the isValidUser method test. Here’s what it might look like:

public class UserServiceTest {

   private static final String PASSWORD = "password";

   private static final User ENABLED_USER =
           new User("user id", "hash", true);

   private static final User DISABLED_USER =
           new User("disabled user id", "disabled user password hash", false);
  
   private UserRepository userRepository;
   private PasswordEncoder passwordEncoder;
   private UserService userService;

   @Before
   public void setup() {
       userRepository = createUserRepository();
       passwordEncoder = createPasswordEncoder();
       userService = new UserService(userRepository, passwordEncoder);
   }

   @Test
   public void shouldBeValidForValidCredentials() {
       boolean userIsValid = userService.isValidUser(ENABLED_USER.getId(), PASSWORD);
       assertTrue(userIsValid);

       // userRepository had to be used to find a user with id="user id"
       verify(userRepository).findById(ENABLED_USER.getId());

       // passwordEncoder had to be used to compute a hash of "password"
       verify(passwordEncoder).encode(PASSWORD);
   }

   @Test
   public void shouldBeInvalidForInvalidId() {
       boolean userIsValid = userService.isValidUser("invalid id", PASSWORD);
       assertFalse(userIsValid);

       InOrder inOrder = inOrder(userRepository, passwordEncoder);
       inOrder.verify(userRepository).findById("invalid id");
       inOrder.verify(passwordEncoder, never()).encode(anyString());
   }

   @Test
   public void shouldBeInvalidForInvalidPassword() {
       boolean userIsValid = userService.isValidUser(ENABLED_USER.getId(), "invalid");
       assertFalse(userIsValid);

       ArgumentCaptor<String> passwordCaptor = ArgumentCaptor.forClass(String.class);
       verify(passwordEncoder).encode(passwordCaptor.capture());
       assertEquals("invalid", passwordCaptor.getValue());
   }

   @Test
   public void shouldBeInvalidForDisabledUser() {
       boolean userIsValid = userService.isValidUser(DISABLED_USER.getId(), PASSWORD);
       assertFalse(userIsValid);

       verify(userRepository).findById(DISABLED_USER.getId());
       verifyZeroInteractions(passwordEncoder);
   }

   private PasswordEncoder createPasswordEncoder() {
       PasswordEncoder mock = mock(PasswordEncoder.class);
       when(mock.encode(anyString())).thenReturn("any password hash");
       when(mock.encode(PASSWORD)).thenReturn(ENABLED_USER.getPasswordHash());
       return mock;
   }

   private UserRepository createUserRepository() {
       UserRepository mock = mock(UserRepository.class);
       when(mock.findById(ENABLED_USER.getId())).thenReturn(ENABLED_USER);
       when(mock.findById(DISABLED_USER.getId())).thenReturn(DISABLED_USER);
       return mock;
   }
}

Diving beneath the API

Mockito provides a readable, convenient API, but let’s explore some of its internal workings so as to understand its limitations and avoid weird errors.

Let’s examine what’s going on inside Mockito when the following snippet is run:

// 1: create
PasswordEncoder mock = mock(PasswordEncoder.class);
// 2: stub
when(mock.encode("a")).thenReturn("1");
// 3: act
mock.encode("a");
// 4: verify
verify(mock).encode(or(eq("a"), endsWith("b")));

Obviously, the first line creates a mock. Mockito uses ByteBuddy to create a subclass of the given class. The new class object have a generated name like demo.mockito.PasswordEncoder$MockitoMock$1953422997, its equals() will act as checking identity, and hashCode() will return an identity hash code. Once the class is generated and loaded, its instance is created using Objenesis.

Let’s look at the next line:

when(mock.encode("a")).thenReturn("1");

The ordering is important: The first statement executed here is mock.encode("a"), which will invoke encode() on the mock with a default return value of null. So really, we’re passing null as an argument of when(). Mockito doesn’t care what exact value is being passed to when() because it stores information about a mocked method’s invocation in so-called ‘ongoing stubbing’ when that method is invoked. Later, when we’re calling when(), Mockito pulls that ongoing stubbing object and returns it as the result of when(). Then we call thenReturn(“1”) on the returned ongoing stubbing object.

The third line, mock.encode("a"); is simple: We’re calling the stubbed method. Internally, Mockito saves this invocation for further verification and returns the stubbed invocation answer; in our case, it’s the string 1.

In the fourth line (verify(mock).encode(or(eq("a"), endsWith("b")));), we’re asking Mockito to verify that there was an invocation of encode() with those specific arguments.

verify() is executed first, which turns Mockito’s internal state into verification mode. It’s important to understand that Mockito keeps its state in a ThreadLocal. This makes it possible to implement a nice syntax but, on the other hand, it can lead to weird behavior if the framework is used improperly (if you attempt to use argument matchers outside of verification or stubbing, for example).

So how does Mockito create an or matcher? First, eq("a") is called, and an equals matcher is added to the matchers stack. Second, endsWith("b") is called, and an endsWith matcher is added to the stack. At last, or(null, null) is called—it uses the two matchers it pops from the stack, creates the or matcher, and pushes that to the stack. Finally, encode() is called. Mockito then verifies that the method was invoked the expected number of times and with the expected arguments.

While argument matchers can’t be extracted to variables (because it changes the call order), they can be extracted to methods. This preserves the call order and keeps the stack in the right state:

verify(mock).encode(matchCondition());
…
String matchCondition() {
   return or(eq("a"), endsWith("b"));
}

Changing Default Answers

In previous sections, we created our mocks in such a way that when any mocked methods are called, they return an “empty” value. This behavior is configurable. You can even provide your own implementation of org.mockito.stubbing.Answer if those provided by Mockito are not suitable, but it might be an indication that something is wrong when unit tests get too complicated. Remember the KISS principle!

Let’s explore Mockito’s offering of predefined default answers:

  • RETURNS_DEFAULTS is the default strategy; it isn’t worth mentioning explicitly when setting up a mock.

  • CALLS_REAL_METHODS makes unstubbed invocations call real methods.

  • RETURNS_SMART_NULLS avoids a NullPointerException by returning SmartNull instead of null when using an object returned by an unstubbed method call. You’ll still fail with a NullPointerException, but SmartNull gives you nicer stack trace with the line where unstubbed method was called. This makes it worthwhile to have RETURNS_SMART_NULLS be the default answer in Mockito!

  • RETURNS_MOCKS first tries to return ordinary “empty” values, then mocks, if possible, and null otherwise. The criteria of emptiness differs a bit from what we’ve seen earlier: Instead of returning null for strings and arrays, the mocks created with RETURNS_MOCKS return empty strings and empty arrays, respectively.

  • RETURNS_SELF is useful for mocking builders. With this setting, a mock will return an instance of itself if a method is called that returns something of a type equal to the class (or a superclass) of the mocked class.

  • RETURNS_DEEP_STUBS goes deeper than RETURNS_MOCKS and creates mocks that are able to return mocks from mocks from mocks, etc. In contrast to RETURNS_MOCKS, the emptiness rules are default in RETURNS_DEEP_STUBS, so it returns null for strings and arrays:

interface We { Are we(); }
interface Are { So are(); }
interface So { Deep so(); }
interface Deep { boolean deep(); }
...
We mock = mock(We.class, Mockito.RETURNS_DEEP_STUBS);
when(mock.we().are().so().deep()).thenReturn(true);
assertTrue(mock.we().are().so().deep());

Naming a Mock

Mockito allows you to name a mock, a feature useful if you have a lot of mocks in a test and need to distinguish them. That said, needing to name mocks might be a symptom of poor design. Consider the following:

PasswordEncoder robustPasswordEncoder = mock(PasswordEncoder.class);
PasswordEncoder weakPasswordEncoder = mock(PasswordEncoder.class);
verify(robustPasswordEncoder).encode(anyString());

Mockito will complain, but because we haven’t formally named the mocks, we don’t know which one:

Wanted but not invoked:
passwordEncoder.encode(<any string>);

Let’s name them by passing in a string on construction:

PasswordEncoder robustPasswordEncoder = mock(PasswordEncoder.class, "robustPasswordEncoder");
PasswordEncoder weakPasswordEncoder = mock(PasswordEncoder.class, "weakPasswordEncoder");
verify(robustPasswordEncoder).encode(anyString());

Now the error message is friendlier and clearly points to robustPasswordEncoder:

Wanted but not invoked:
robustPasswordEncoder.encode(<any string>);

Implementing Multiple Mock Interfaces

Sometimes, you may wish to create a mock that implements several interfaces. Mockito is able to do that easily, like so:

PasswordEncoder mock = mock(
       PasswordEncoder.class, withSettings().extraInterfaces(List.class, Map.class));
assertTrue(mock instanceof List);
assertTrue(mock instanceof Map);

Listening Invocations

A mock can be configured to call an invocation listener every time a method of the mock was called. Inside the listener, you can find out whether the invocation produced a value or if an exception was thrown.

InvocationListener invocationListener = new InvocationListener() {
   @Override
   public void reportInvocation(MethodInvocationReport report) {
       if (report.threwException()) {
           Throwable throwable = report.getThrowable();
           // do something with throwable
           throwable.printStackTrace();
       } else {
           Object returnedValue = report.getReturnedValue();
           // do something with returnedValue
           System.out.println(returnedValue);
       }
   }
};
PasswordEncoder passwordEncoder = mock(
       PasswordEncoder.class, withSettings().invocationListeners(invocationListener));
passwordEncoder.encode("1");

In this example, we’re dumping either the returned value or a stack trace to a system output stream. Our implementation does roughly the same as Mockito’s org.mockito.internal.debugging.VerboseMockInvocationLogger (don’t use this directly, it’s internal stuff). If logging invocations is the only feature you need from the listener, then Mockito provides a cleaner way to express your intent with the verboseLogging() setting:

PasswordEncoder passwordEncoder = mock(
       PasswordEncoder.class, withSettings().verboseLogging());

Take notice, though, that Mockito will call the listeners even when you’re stubbing methods. Consider the following example:

PasswordEncoder passwordEncoder = mock(
       PasswordEncoder.class, withSettings().verboseLogging());
// listeners are called upon encode() invocation
when(passwordEncoder.encode("1")).thenReturn("encoded1");
passwordEncoder.encode("1");
passwordEncoder.encode("2");

This snippet will produce an output similar to the following:

############ Logging method invocation #1 on mock/spy ########
passwordEncoder.encode("1");
   invoked: -> at demo.mockito.MockSettingsTest.verboseLogging(MockSettingsTest.java:85)
   has returned: "null"

############ Logging method invocation #2 on mock/spy ########
   stubbed: -> at demo.mockito.MockSettingsTest.verboseLogging(MockSettingsTest.java:85)
passwordEncoder.encode("1");
   invoked: -> at demo.mockito.MockSettingsTest.verboseLogging(MockSettingsTest.java:89)
   has returned: "encoded1" (java.lang.String)

############ Logging method invocation #3 on mock/spy ########
passwordEncoder.encode("2");
   invoked: -> at demo.mockito.MockSettingsTest.verboseLogging(MockSettingsTest.java:90)
   has returned: "null"

Note that the first logged invocation corresponds to calling encode() while stubbing it. It’s the next invocation that corresponds to calling the stubbed method.

Other Settings

Mockito offers a few more settings that let you do the following:

  • Enable mock serialization by using withSettings().serializable().
  • Turn off recording of method invocations to save memory (this will make verification impossible) by using withSettings().stubOnly().
  • Use the constructor of a mock when creating its instance by using withSettings().useConstructor(). When mocking inner non-static classes, add an outerInstance() setting, like so: withSettings().useConstructor().outerInstance(outerObject).

If you need to create a spy with custom settings (such as a custom name), there’s a spiedInstance() setting, so that Mockito will create a spy on the instance you provide, like so:

UserService userService = new UserService(
       mock(UserRepository.class), mock(PasswordEncoder.class));
UserService userServiceMock = mock(
       UserService.class,
       withSettings().spiedInstance(userService).name("coolService"));

When a spied instance is specified, Mockito will create a new instance and populate its non-static fields with values from the original object. That’s why it’s important to use the returned instance: Only its method calls can be stubbed and verified.

Note that, when you create a spy, you’re basically creating a mock that calls real methods:

// creating a spy this way...
spy(userService);
// ... is a shorthand for
mock(UserService.class,
    withSettings()
            .spiedInstance(userService)
            .defaultAnswer(CALLS_REAL_METHODS));

When Mockito Tastes Bad

It’s our bad habits that make our tests complex and unmaintainable, not Mockito. For example, you may feel the need to mock everything. This kind of thinking leads to testing mocks instead of production code. Mocking third-party APIs can also be dangerous due to potential changes in that API that can break the tests.

Though bad taste is a matter of perception, Mockito provides a few controversial features that can make your tests less maintainable. Sometimes stubbing isn’t trivial, or an abuse of dependency injection can make recreating mocks for each test difficult, unreasonable or inefficient.

Clearing Invocations

Mockito allows for clearing invocations for mocks while preserving stubbing, like so:

PasswordEncoder passwordEncoder = mock(PasswordEncoder.class);
UserRepository userRepository = mock(UserRepository.class);
// use mocks
passwordEncoder.encode(null);
userRepository.findById(null);
// clear
clearInvocations(passwordEncoder, userRepository);
// succeeds because invocations were cleared
verifyZeroInteractions(passwordEncoder, userRepository);

Resort to clearing invocations only if recreating a mock would lead to significant overhead or if a configured mock is provided by a dependency injection framework and stubbing is non-trivial.

Resetting a Mock

Resetting a mock with reset() is another controversial feature and should be used in extremely rare cases, like when a mock is injected by a container and you can’t recreate it for each test.

Overusing Verify

Another bad habit is trying to replace every assert with Mockito’s verify(). It’s important to clearly understand what is being tested: interactions between collaborators can be checked with verify(), while confirming the observable results of an executed action is done with asserts.

Mockito Is about Frame of Mind

Using Mockito is not just a matter of adding another dependency, it requires changing how you think about your unit tests while removing a lot of boilerplate.

With multiple mock interfaces, listening invocations, matchers and argument captors, we’ve seen how Mockito makes your tests cleaner and easier to understand, but like any tool, it must be used appropriately to be useful. Now armed with the knowledge of Mockito’s inner workings, you can take your unit testing to the next level.

About the author

Ivan Pavlov, Russia
member since January 20, 2016
Ivan has both back-end and front-end software development experience. He enjoys developing software from the ground up, learning new technologies, refactoring legacy code, and making his customers satisfied. He designed and developed software for banks, medical organizations, and city administration. [click to continue...]
Hiring? Meet the Top 10 Freelance Java Developers for Hire in July 2017

Comments

comments powered by Disqus
Subscribe
The #1 Blog for Engineers
Get the latest content first.
No spam. Just great engineering posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
You can edit your subscription preferences here.
Trending articles
Relevant Technologies
About the author
Ivan Pavlov
Java Developer
Ivan has both back-end and front-end software development experience. He enjoys developing software from the ground up, learning new technologies, refactoring legacy code, and making his customers satisfied. He designed and developed software for banks, medical organizations, and city administration.