Hey there! 👻

Did you switch to Kotlin or yet wondering? Just do it!

However, there're always some inconveniences like the one I will describe in this post.

Problem

You started happy coding your amazing apps in Kotlin but when unit testing time has come... Bam! You cannot test final classes with Mockito 1.x and receive the following error:

Mockito cannot mock/spy following:
– final classes
– anonymous classes
– primitive types

By default the Kotlin classes are final.

There're mainly three solutions:

  • Switch to Mockito 2.x
  • Using interfaces which classes under testing should implement and then test the interfaces instead of the concrete classes
  • Use the proposed solution which works with Mockito 1.x

Solution

Starting from Kotlin 1.0.6 you can use the all-open compiler plugin which makes classes annotated with a specific annotation and their members open without explicitly using the keyword open in front of the class declaration.

First, we have to create the annotation class:

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class TestOpen 

Second, we need to apply the all-open plugin in the app's build.gradle file:

buildscript {  
    ext.kotlin_version = '1.0.6'
    repositories {
        jcenter()
    }
    dependencies {
        ...
        classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
    }
}

And configure it in the module's build.gradle file:

apply plugin: 'kotlin-allopen'

allOpen {  
    annotation("[PATH_TO_ANNOTATION_CLASS].TestOpen")
}

And then simply annotate the classes with this annotation:

@TestOpen
class TasksRepository {
...
}

Beware!

Classes become open not only during tests!
all-open plugin actually opens all annotated classes for testing configurations!

Hope that this post will save you some time researching the issue!

Happy coding! 🙏🏼