Everyday Mockito
Everyday Mockito
Engineering
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. In this article, we cover multiple
mock interfaces, listening invocations, matchers, and argument captors, and see firsthand how
Mockito makes your tests cleaner and easier to understand.
authors are vetted experts in their fields and write on topics in which they have demonstrated
experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
By continuing to use this site you agree to our Cookie Policy. Got it
By Ivan Pavlov
Verified Expert in Engineering
17 Years of Experience
Ivan has both back-end and front-end development experience. He has built
software for banks, medical organizations, and city administration.
Read More
EXPERTISE
SHARE
Editor’s note: This article was updated by our editorial team on January 6, 2023. It
has been modified to include recent sources and to align with our current editorial
standards.
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 cover creating and configuring mocks and using them to verify the
expected behavior of the system being tested. We also explore Mockito’s internals to
better understand its design and caveats. We use 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.
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 use slightly different implementations of these dependencies when
testing different behaviors. A traditional, well-known approach here 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 of doubles include fakes, mocks, spies, dummies, etc.
We focus only on two types of test doubles, “mocks” and “spies,” as these are heavily
employed by Mockito.
What Is a Mock?
In unit testing, a mock is a created 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 a changed state.
What Is a Spy?
A spy is the other type of test double that Mockito creates. In contrast to creating a
mock, 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.
How Is Mockito Set Up?
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"
For those like me who still prefer Maven, just add Mockito to your dependencies:
<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.
Let’s translate our conceptual definitions of mocks and spies into concrete code
functions for use in Mockito unit testing.
A Simple Demo
Before discussing code examples, 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:
User:
PasswordEncoder:
UserService:
As we discuss various testing strategies in this article, we will reference our simple
demo.
Notice the static import for Mockito. For the rest of this article, we 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 could not originally mock final classes and final or static methods, but the
MockMaker plugin is now available.
Also note that the methods equals() and hashCode() cannot be mocked.
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:
Creating a spy and creating a mock do not differ much. And 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 requires partial mocking. In
those cases, you can just create a spy and stub some of its methods to get the behavior
you want.
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:
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.” This strategy uses Mockito’s thenReturn call:
when(passwordEncoder.encode("1")).thenReturn("a");
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 preferred because it is typesafe and more readable. In rare
circumstances you may be forced to use the second way, e.g., 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
//“do something when this mock’s method is called with the following argumen
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");
//do
doReturn("a", "b").when(passwordEncoder).encode("1");
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.
then() , an alias to thenAnswer() , and doAnswer() achieve the same thing, which is
//thenAnswer
when(passwordEncoder.encode("1")).thenAnswer(
invocation -> invocation.getArgument(0) + "!");
//doAnswer
doAnswer(invocation -> invocation.getArgument(0) + "!")
.when(passwordEncoder).encode("1");
Alternatively, you may call the real method of a class (not applicable to interfaces):
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 a very informative message. Consider the
following snippet:
when(passwordEncoder.encode("1")).thenCallRealMethod();
Kudos to the Mockito developers for caring enough to provide such thorough
descriptions!
Throwing Exceptions
//thenThrow
when(passwordEncoder.encode("1")).thenThrow(new IllegalArgumentException());
//doThrow
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());
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:
//thenThrow
when(passwordEncoder.encode("1")).thenThrow(IllegalArgumentException.class);
//doThrow
doThrow(IllegalArgumentException.class).when(passwordEncoder).encode("1");
That said, Mockito cannot validate an exception class in the same way as it validates
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");
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.
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:
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.
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 others) 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.
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 rewrote
that line in plain English, it would be “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, it can’t be done. You can’t write code like this:
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 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:
d h
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 made lightly since the need to match arguments in a non-trivial way
indicates either a design problem or a too-complicated test.
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.
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 this:
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 on the
org.mockito.AdditionalMatchers class.
Here we’ve combined the results of two argument matchers: eq("1") and
contains("a") . The final expression, or(eq("1"), contains("a")) , may be
which are value comparisons applicable for primitive values and instances of
java.lang.Comparable .
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.”
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 as they are for stubbing:
verify(passwordEncoder).encode(anyString());
By default, Mockito verifies that the method was called once, but you can verify any
number of invocations:
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 specified period, 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:
Mockito also allows you to verify the call order in a group of mocks. It’s not a feature
to use very often, but it may be useful if the order of invocations is important.
Consider the following example:
If we rearrange the order of the simulated calls, the test will fail with
VerificationInOrderFailure .
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 able to verify that a method was called, and receive the
argument values it was called with.
Let’s create a mock of PasswordEncoder , call encode() , capture the argument, and
check its value:
The same technique can be used for capturing variable arity method arguments (also
known as varargs).
Now that we know a lot more about testing functionalities, it’s time to get back to our
Java Mockito demo. Let’s write the isValidUser method test. Here’s what it might
look like:
@Before
public void setup() {
userRepository = createUserRepository();
passwordEncoder = createPasswordEncoder();
userService = new UserService(userRepository, passwordEncoder);
}
@Test
public void shouldBeValidForValidCredentials() {
boolean userIsValid = userService.isValidUser(ENABLED_USER.getId(), P
assertTrue(userIsValid);
@Test
public void shouldBeInvalidForInvalidId() {
boolean userIsValid = userService.isValidUser("invalid id", PASSWORD)
assertFalse(userIsValid);
@Test
public void shouldBeInvalidForInvalidPassword() {
boolean userIsValid = userService.isValidUser(ENABLED_USER.getId(), "
assertFalse(userIsValid);
@Test
public void shouldBeInvalidForDisabledUser() {
boolean userIsValid = userService.isValidUser(DISABLED_USER.getId(),
assertFalse(userIsValid);
verify(userRepository).findById(DISABLED_USER.getId());
verifyZeroInteractions(passwordEncoder);
}
Mockito provides a readable, convenient API, but let’s explore some of its internal
workings to understand its limitations and avoid weird errors.
Ordering Calls
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 has a generated name like
demo.mockito.PasswordEncoder$MockitoMock$1953422997 ; its equals() will act as an
identity check, and hashCode() will return an identity hash code. Once the class is
generated and loaded, its instance is created using Objenesis.
when(mock.encode("a")).thenReturn("1");
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 .
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. 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 they change 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 were called, they returned 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. When in doubt, strive for
simplicity.
Useful for mocking builders. With this setting, a mock will return an
RETURNS_SELF instance of itself if a method is called that returns an object of a
type equal to the class (or a superclass) of the mocked class.
Naming a Mock
Mockito allows you to name a mock, a useful feature 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:
Mockito will complain with an error message, but because we haven’t formally named
the mocks, we don’t know which password encoder is being referred to:
Sometimes, you may wish to create a mock that implements several interfaces.
Mockito is able to do that easily:
Listening Invocations
A mock can be configured to call an invocation listener every time a method of the
mock is called. Inside the listener, you can find out whether the invocation produced a
value or if an exception was thrown.
h l ’ d h h d l k
In this example, we’re dumping either the returned value or a stack trace to a system
output stream. Our implementation does roughly what Mockito’s
org.mockito.internal.debugging.VerboseMockInvocationLogger does (but this is an
Notice that Mockito will call the listeners even when you’re stubbing methods.
Consider the following example:
Other Settings
Mockito offers a few more settings that let you do the following:
Turn off recording of method invocations to save memory (this will make
verification impossible) by using withSettings().stubOnly() .
If you need to create a spy with custom settings (such as a custom name), there’s a
spiedInstance() setting such that Mockito will create a spy on the instance you
provide:
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));
Our bad habits 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 testing production code. Mocking third-party APIs can also
be dangerous due to potential changes in that API that can break the tests.
Clearing Invocations
Mockito allows for clearing invocations for mocks while preserving stubbing:
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.
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.
Mockito is used to create and configure mocked objects (e.g., a mock or spy) when unit
testing.
Hamburg, Germany
Member since March 7, 2016
Ivan has both back-end and front-end development experience. He has built software for banks, medical
organizations, and city administration.
Read More
authors are vetted experts in their fields and write on topics in which they have demonstrated
experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
EXPERTISE
Hire Ivan
TRENDING ARTICLES
ENGINEERING › TECHNOLOGY
Sign Me Up
Toptal Developers
Hire a Developer
or
Apply as a Developer
END-TO-END SOLUTIONS
Artificial Intelligence
Cloud Services
MARKETING SERVICES
Digital Marketing
Growth Marketing
ABOUT CONTACT
Top 3% Contact Us
Community FAQ
Specialized Services
About Us