To demonstrate the challenge associated with testing closed classes in Kotlin, we can walk through a simple, but common, example. In this code snippet, we've defined a class, SimpleGreeter, that implements the GreetingProvider interface:
class SimpleGreeter() : GreetingProvider {
override fun getGreeting(): String {
return "Hi"
}
}
Now, we can try to mock this SimpleGreeter class with Mockito:
val mockProvider = Mockito.mock(SimpleGreeter::class.java) // Runtime error
However, mocking SimpleGreeter in this way will result in an error. That error will look something like this:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class SimpleGreeter
Mockito cannot mock/spy because :
- final class
Essentially, what the error is indicating is that Mockito can't mock final classes, and because all classes in Kotlin are final by default, this prevents us from using Mockito. So, how do we mock our Kotlin classes without marking everything as open?
In the case of Mockito, thankfully, this is quite easy to solve. We can simply add the mockito-inline dependency alongside our existing Mockito2 dependency:
// https://mvnrepository.com/artifact/org.mockito/mockito-inline
testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.27.0'
After adding the mockito-inline dependency, the mocking of final classes will work without marking them as open.