From Punched Cards to Prompts
AndroidIntroduction When computer programming was young, code was punched into cards. That is, holes were punched into a piece of cardboard in a format...
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.
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.
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.
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 Matcher
s 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 String
s and
will verify that the parameter is a String
type.
This change is also true for Integer
s, List
s, and other types as well.
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!
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.
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.
Introduction When computer programming was young, code was punched into cards. That is, holes were punched into a piece of cardboard in a format...
Jetpack Compose is a declarative framework for building native Android UI recommended by Google. To simplify and accelerate UI development, the framework turns the...
Big Nerd Ranch is chock-full of incredibly talented people. Today, we’re starting a series, Tell Our BNR Story, where folks within our industry share...