https://static.javadoc.io/org.mockito/mockito-core/2.23.0/org/mockito/logo@2x.png

Mockito 2.x Migration Session Recording - Droidcon UK 2018

Hazem Saleh
ProAndroidDev
Published in
7 min readNov 14, 2018

--

Mockito 2.x solves many problems that most of the Android developers were having in their unit tests in Mockito 1.x. But what if you are having today large unit 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.x 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 (including demos). This session is presented in Droidcon UK 2018 (@25 October).

Video

Attached below the session video (In case you have difficulty viewing the video, you can watch it directly from the URL below):
https://skillsmatter.com/skillscasts/12162-upgrading-android-app-unit-tests-to-mockito-2-x

Slides

Attached below the slides.

Presentation Transcript

  1. Mockito 2.x Migration for Hazem Saleh Software Architect, @Viacom, New York
  2. About
    § 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. Outline
    § 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. Challenges of Mockito 1.x
    § Mocking final methods was not supported.
    § Mocking final classes was not supported. Typical Exception when you try to mock final classes or methods
  5. Challenges of Mockito 1.x
    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.
  6. Demo - Mockito 1.x challenges
    GitHub Repo: https://github.com/hazems/android-demo-app/tree/mockito1x
  7. Mockito 2.x advantages
    § Mocking final methods is supported.
    § Mocking final classes is supported.
    § Java 8 is supported.
    § Migration from CGLIB to ByteBuddy.
  8. Migrating Mockito 1.x unit tests to Mockito 2.x
    § 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. Migrating Mockito 1.x unit tests to Mockito 2.x (True Story)
    § 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. Tip #1 - Use Right Matchers
    § Never forget to always use org.mockito.ArgumentMatchers instead of the old org.mockito.Matchers.
  11. Tip #2 - anyString() does not match null anymore
    § 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.
  12. Tip #2 — anyString() does not match null anymore
    MessageHandler::handle()
    MessageProcessor::process()
    MessageFormatter::format()
  13. Tip #2 — anyString() does not match null anymore
    MessageHandler::handle()
    MessageProcessor::process()
    MessageFormatter::format()
    In Mockito 2.x, This will fail since anyString() != null although this works in Mockito 1.x.
  14. Tip #2 — anyString() does not match null anymore
    MessageHandler::handle()
    MessageProcessor::process()
    MessageFormatter::format()
    Now, format() is properly verified Mock dependencies properly
    • This works in Mockito 2.x.
    • Mockito 2.x reveals some of incomplete written unit tests that was written in Mockito 1.x.
  15. Tip #3 - anyInt() does not match long literals anymore
    § 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. Tip #4 - Say Goodbye to Mockito’s Whitebox
    § 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).
  17. Tip #5 - API Changes of InvocationOnMock
    §getArgumentAt() is removed from InvocationOnMock, the following line will not compile in Mockito 2.x.
  18. Tip #6 - Use the proper PowerMock’s Mockito API extension
    § 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. Tip #7 - Always use compatible versions of PowerMock with Mockito
    § 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. Tip #8 - Move away from PowerMock
    § 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. Tip #9 - Allocate time to clean up unit tests
    § 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.
  22. Demo - Mockito 2.x migrated unit tests
    GitHub Repo: https://github.com/hazems/android-demo-app/tree/mockito2x
  23. Mocking third party static method APIs
    § 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.
  24. Mocking third party static method APIs Demo
    GitHub Repo: https://github.com/hazems/android-demo-app/tree/mockito2x
  25. What about Kotlin
    § 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”
  26. Kotlin Mockito Demo
    GitHub Repo: https://github.com/hazems/android-demo-app/tree/migrate_kotlin
  27. Conclusion
    § 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.
  28. Blog: https://medium.com/@hazems Twitter: @hazems

If you like this article, I appreciate your support to share this article with others to let the great Android community know.

--

--

Open source enthusiast, Apache PMC, Sr Software Engineer in @Facebook NY, Author of 5 tech books (one of them is a best selling). All opinions are my own.