Migrating from Java to Kotlin — War story 2

Thank you Autodraw and Google Slides :D

So you’ve made headway with migrating your Android codebase to Kotlin and you’re about to start migrating your unit tests. The first challenge with migrating unit tests from Java to Kotlin is that classes in Kotlin are final by default and Mockito does not mock final classes.

Enter Mockito 2…

One of the major selling points of migrating to Mockito 2 is it’s ability to mock final classes. The first step is to add the dependency to your build.gradle file. You can see all the latest version numbers here.

testCompile 'org.mockito:mockito-core:2.8.47'

Next, you‘ll need to create a new folder named mockito-extensions in test/resources. In the new folder, you’ll create a new file and name it org.mockito.plugins.MockMaker. This file should contain just the mock-maker-inline text on the first line.

mock-maker-inline

Mockito Matchers…

You’ll notice that the compiler returns a lot of errors from the Mockito matcher methods. You might be exasperated at this point especially when the same test passed in Java and the only change you made was to convert it to Kotlin. Do not despair!

This is happening because those methods return null and while Java was gracious enough to allow it, Kotlin isn’t having any of that. This actually works as intended because one of the reasons we hopped on Kotlin was to avoid the billion dollar mistake. :)

The cleanest way I know to resolve this so far is to use methods from the mockito-kotlin library by Niek Haarman instead. It’s used similarly to the original Mockito methods. You’ll need to double check your methods to ensure that you are importing from the library rather than from Mockito.

Mockito matchers in Java are implemented as written below:

verify(human).doesHumanThings(any(Human.class), eq(I_AM_GROOT));

While in Kotlin with nhaarman’s library, we have:

verify(human).doesHumanThings(any<Human>(), eq(I_AM_GROOT))

ArgumentCaptor.capture()

The third challenge has to do with argument captors. I’m calling this out specifically because while it also returns null like the other Mockito argument matchers, it is implemented a little differently.

A typical ArgumentCaptor class in Java is used like this.

ArgumentCaptor<Human> captor = forClass(Human.class);

verify(human).doesHumanThings(captor.capture());

With nhaarman’s library, all we need to do is to rewrite in Kotlin like so…

val captor = argumentCaptor<Human>()

verify(human).doesHumanThings(captor.capture())

Hopefully with all these, you should be on your way to achieving a 100% testable Kotlin codebase.

Want to read my first Java to Kotlin War story? Find it here!

Thought this was great? Please don’t forget to “Recommend” and “Share”.