Upcoming and OnDemand Webinars View full list

Mockito 2: Updates And Issues

Brian Gardner

Mockito, the popular Java test double library, got a major version bump when it moved to 2.1 last fall. It’s been changing quickly—we’re currently at 2.8.53 at the time of this writing. We’ve been watching those changes, and are excited about a lot of the new features available. That said, there also some things to watch out for. In this post, we will cover some of those exciting new developments, the problems you may run into, and some workarounds.

New Features

Unused Stubs

One new feature that you can now enable is a check for unused stubs in your test.
Use a new test rule that will notify you when tests stubs go unused.
Your tests will still pass but those logs are a good indication that you should
clean up any unnecessary stubbing in your tests.
Here is an example of a test with an unused stub.

@RunWith(JUnit4.class)
public class UnusedStubText {
    @Rule
    public MockitoRule mRule = MockitoJUnit.rule();

    @Test
    public void itFindsUnusedStubs() {
        User user = mock(User.class);
        User unusedUser = mock(User.class);
        when(unusedUser.getId()).thenReturn(1);
        when(user.getId()).thenReturn(1);
        assertThat(user.getId(), is(equalTo(1)));
    }
}

The first thing to note is the rule at the top of the test class.

@Rule
public MockitoRule mRule = MockitoJUnit.rule();

This rule will automatically keep track of your test stubs and notify you when
they are not used.
If you run the above test, it will pass, but you will see this log output.

[MockitoHint] UnusedStubText.itFindsUnusedStubs (see javadoc for MockitoHint):
[MockitoHint] 1. Unused -> at com.bgardner.mockitotest.User.getId(User.java:9)

It tells you the test method where the stub was not used as well as the method
that was not called on your stub.
When you see these in your tests it is a good indication that you can either
remove the stub, or that your code isn’t functioning as you would expect.

Lazy Verification

Another new feature in Mockito 2.1 is lazy verification.
This allows your tests to run to completion and it will tell you all of the
failed verifications instead of stopping at the first.
This will give you a more complete view about the incomplete parts of your code
under test.
This test shows how to enable lazy verification.

@RunWith(JUnit4.class)
public class LazyVerificationTest {
    @Rule
    public VerificationCollector mCollector = MockitoJUnit.collector();

    @Test
    public void itCollectsAllVerificationErrors() {
        User user = mock(User.class);
        verify(user).getId();
        verify(user).getName();
    }
}

Just like the previous example, you need to enable a new test rule.
You can add multiple rules to the same test class to get all of the
functionality.

@Rule
public VerificationCollector mCollector = MockitoJUnit.collector();

Once the VerificationCollector rule is enabled you will see all of your
incorrect verifications in the test output.
Without this new rule the above test would only show the first failed
verification.

Wanted but not invoked:
user.getId();
-> at com.bgardner.mockitotest.User.getId(User.java:9)
Actually, there were zero interactions with this mock.

With the rule enabled you would see a failure for both of the verifications
along with a failure message indicating multiple failures.

org.mockito.exceptions.base.MockitoAssertionError: There were multiple verification failures:
1. Wanted but not invoked:
user.getId();
-> at com.bgardner.mockitotest.User.getId(User.java:9)
Actually, there were zero interactions with this mock.

2. Wanted but not invoked:
user.getName();
-> at com.bgardner.mockitotest.User.getName(User.java:17)
Actually, there were zero interactions with this mock.

Things To Watch Out For

Along with the new features available in Mockito 2, there are also some changes
to watch out for.
The first is that the mockito-all dependency is no longer available.
mockito-all contained other dependencies which are no longer needed when using
Gradle, so make sure you are using the mockito-core dependency instead.

Another notable change is that Mockito has separated their Matcher classes from
Hamcrest.
Methods such as argThat() used to be declared on the Matcher object.
These methods have since been moved to the MockitoHamcrest object so ensure you
update your imports to use the correct class.

Finally, the any() class of Matchers now perform null checks and will fail if
null is given as an argument.
For instance, the anyString() method will no longer match null for Strings and
will verify that the parameter is a String type.
This change is also true for Integers, Lists, and other types as well.

The Big Change

One of the biggest changes to Mockito is the ability to mock final classes.
It should be noted that this is an incubating feature so you may run into
issues, one of which will be discussed later.
This feature has been a long time coming and will make certain test cases easier
in Android.

Since this is incubating it needs to be enabled in your project.
First create a new file at this path.

src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker

This only needs a single line in it.

mock-maker-inline

With this in place you will be able to mock final classes in your Android
projects!

One More Thing

If you want to use final class mocking with Robolectric, you need to be aware of
an issue between it and Mockito.
On previous versions of Robolectric, the final class mocking did not work because
both Robolectric and Mockito manipulate the byte code when running your tests.
You also aren’t able to mock default methods in
interfaces on older versions of Mockito.
To avoid these issues, make sure you are running at least version 3.3 of
Robolectric to resolve the final class mocking.
Use at least version 2.7.12 of Mockito 2 to enable default method mocking.

Final Thoughts

Mockito’s final mocking is a big step forward for Android testing.
In cases like Retrofit, you may rely on third party libraries that use final
classes you want to mock in your tests.
Having the ability to mock those objects makes unit testing your code much
easier.

You can learn more about mocking, testing and streamlining your code in our Advanced Android class.

Not Happy with Your Current App, or Digital Product?

Submit your event

Let's Discuss Your Project

Let's Discuss Your Project