Mockito 2.x solves many problems that most of the Android developers were having in their tests in Mockito 1.x. But what if you are having today large tests written in Mockito 1.x and PowerMock, will it be an easy task to migrate?
Unfortunately, it is not a straightforward task since Mockito 2 is not fully compatible with the old behaviour of Mockito 1.x. Adding to this complexity, If you are having PowerMock in your old tests, then you will have to face another dimension of complexity since most of PowerMock’s versions are having integration issues with Mockito 2.x.
This session goes through the tips and tricks that you need to consider in order to migrate to and utilize Mockito 2.x. It has demos to show migrating Android app Mockito 1.x tests to Mockito 2.x.
2. § More than fifteen years of experience in software development.
§ Apache Open Source Committer and PMC member.
§ Author of five technical books (One of them is a best selling).
§ DeveloperWorks Contributing Author.
§ Medium Android blogger.
§ DZone MVB.
§ Technical Speaker (Droidcon, AnDevCon, ApacheCon, Geecon,
JavaOne, JavaLand, …etc).
§ An X-IBMer and Currently a Software Architect in Viacom.
3. § Challenges of Mockito 1.x.
§ Demo – Mockito 1.x Challenges.
§ Mockito 2.x advantages.
§ Tips and Tricks for Migrating Mockito 1.x unit tests to
Mockito 2.x.
§ Mockito 2.x migrated tests demos:
§ Mocking Final classes and methods.
§ Mocking Third party static method APIs.
§ What about Kotlin?
§ Demo – Kotlin Mockito.
§ Conclusion.
4. § Mocking final methods was not
supported.
§ Mocking final classes was not
supported.
Typical Exception when you try to mock final classes or methods
5. • To overcome these issues in Mockito 1.x, we needed
to use PowerMock, we have to:
• Change our class runner to PowerMockRunner.
• Prepare the classes that contains final/static
methods for testing.
• Do some extra calls, for example to:
• To mock your intended class using
PowerMockito.mock(yourClass.class).
• To verify static methods, make a call to
PowerMockito.verifyStatic().
• Using PowerMock is not for free, it adds an extra
overhead on the performance of unit tests.
7. § Mocking final methods is
supported.
§ Mocking final classes is
supported.
§ Java 8 is supported.
§ Migration from CGLIB to
ByteBuddy.
8. § Unfortunately, migration from Mockito 1.x to Mockito 2.x is
not an easy task.
§ If you have a large number of unit tests, migrating your unit
tests to Mockito 2.x will most probably a painful task
because Mockito 2.x does not respect some of the old
behaviors of Mockito 1.x.
§ Adding to this complexity, If you are using PowerMock in
your old tests, then you will have to face another dimension
of complexity since most of PowerMock’s versions are
having integration issues with Mockito 2.x.
9. § In the beginning when just changing Mockito version to 2.x
in build.gradle file of a project with tons of unit tests, I
found more than 50% of unit tests were failing due to many
issues:
§ Null pointer exceptions.
§ Compilation errors.
§ No class definition found exceptions.
§ Other un-expected thrown exceptions.
§ In order to overcome these issues, the following steps are
applied to successfully migrate unit tests to Mockito 2.x.
10. § Never forget to always use org.mockito.ArgumentMatchers
instead of the old org.mockito.Matchers.
11. § This can fail many unit tests, In Mockito 2.x, anyString()
does not match null anymore.
§ To solve this problem:
§ Review if your old failing unit tests really intended to assert
nulls. If your unit test is intended to assert null, then simply
replace anyString() with an actual null value.
§ If your unit test is NOT intended to assert null (and was
intended to assert an actual value), then
§ Rewrite your unit test because it was previously not implemented
in a right way.
§ Rewrite here should make sure to return the intended non-null
value to be asserted.
15. §After the upgrade, you may find anyInt() does not
work because it cannot match long literals such as
0L or 10L.
§To solve this problem:
§Replace anyInt() with anyLong().
§Replace anyInt() with the actual long value.
16. § If your old tests use
org.mockito.internal.util.reflection.Whitebox, Do not be
surprised when your unit tests fail.
§ Whitebox is removed from Mockito 2.x.
§ Using Whitebox at first place is a bad testing practice and an
indicator for code testability problem.
§ To solve this problem, you have the following options:
§ (Recommended) Refactor these failing tests for avoiding
using Whitebox (this may require actual code refactoring to
allow testability).
§ (I do not like)You can use PowerMock
(org.powermock.reflect.Whitebox).
18. §Using powermock-api-mockito extension does not
work with Mockito 2.x, you will have the following
exception when running your unit tests
In order to fix this issue,
you should use the new
right Mockito’s 2.x API
extension which is
powermock-api-mockito2.
19. § Mockito 2.x is not a real friend to PowerMock.
§ Always make sure to use compatible versions of PowerMock with
Mockito.
§ For example, if you use PowerMock 1.6.5 or even PowerMock
1.7.0RC2 with Mockito 2.7.1, you will find the following exception
with Mockito donothing() API (To solve it, you need to use
PowerMock 1.7.0RC4).
20. §As shown in the previous two tips, there are multiple
problems of using PowerMock with Mockito 2.x.
§We find it beneficial to move away incrementally
from PowerMock and only depend on Mockito 2.x.
§How to get rid of PowerMock:
§ Using Wrapper Proxy pattern (to be explained in Demo).
21. § Although this tip is not directly
related to migration but I think it is
important.
§ Take the migration task as a chance
to review your project unit tests.
§ Try to allocate enough time to:
§ Fix flacky unit tests.
§ Remove or fix ignored unit tests.
23. § There are certain situations in which you have to deal with
Third party APIs that are static.
§ In order to mock static API in your unit tests, you will have
to use PowerMock!
§ As shown in Tip #8, it is always recommended to just use
Mockito 2.x without PowerMock, so how can we solve this
issue.
§ One of the ideas that can help is to:
§ Create a Wrapper Proxy class for every class having static
methods to provide non-static testable APIs.
§ Remove all direct references to all classes with static methods,
and use the new Wrapper Proxy classes instead.
25. § Mockito currently works fine with Kotlin,
but the syntax is not optimal.
§ A small tip here to have the best
integration experience is to use
Mockito Kotlin:
https://github.com/nhaarman/mockito-
kotlin
§ Mockito Kotlin provides a nice syntactic
sugar in Mockito for Kotlin projects.
§ In Addition,You can use Kluent. Kluent is a
"Fluent Assertions" library written
specifically for Kotlin:
https://github.com/MarkusAmshove/Kluent
Method name can be
`doAction(), does something`
Inline mocking
assertEquals(“Hello World”, result)
result `should equal` “Hello World”
27. § Mockito 1.x has some challenges such as the in-ability of
mocking final classes, and methods.
§ Mockito 2.x solved many of the challenges in Mockito 1.x,
so it is really worth the migration effort.
§ Applying the tips mentioned in this presentation can
facilitate migrating unit tests from Mockito 1.x to Mockito
2.x.
§ Using Wrapper Proxy Pattern and Mockito 2.x framework
can allow you to get rid of PowerMock.