Open getter in Kotlin to use it with Mockito - MissingMethodInvocationException

Viewed 1812

Kotlin can automatically create getters for primary constructor parameters (that's great), and all these getters are final (not open) by default. I have a class (in Kotlin):

open class SongCategory(val id: Long,
                        val type: SongCategoryType,
                        val name: String? = null,
                        var displayName: String? = null,
                        var songs: List<Song>? = null) {
}

I wanted to use it in some Mockito test (in Java):

SongCategory songCategory = mock(SongCategory.class);
// the line below produces MissingMethodInvocationException
when(songCategory.getDisplayName()).thenReturn("Dupa");

This produces MissingMethodInvocationException because Mockito needs the mocked class to be open (not final) and the mocked method getDisplayName() just has to be open but it's not.

I can't make this getter open or create another overriding getter because it's conflicting with a final getter created automatically for a constructor.

I could move these all parameters to a secondary constructor and create all the properties and getters separately. However if I have to write the same boilerplate code as in Java, so what's the sense of using Kotlin then?

Is there some way to use Mockito with Kotlin-compiled getters?

4 Answers

Actually, I've found that the syntax to open a getter is quite simple (although it's not in the official documentation):

open class SongCategory(...
                        open var displayName: String? = null,
                        ...) {
}

This opens both the getter and setter for a property.

You can try to use PowerMock to deal with final method

or alternatively Javasist and its javassist.Modifier

I agree with @Unknown, that there are places where you could use the kotlin-allopen plugin. But in this case, since all you are trying to do is to mock a Kotlin class (that's not open), you just have to add the mockito-inline plugin.

Add the below to your build.gradle:

testImplementation 'org.mockito:mockito-core:2.13.0' // use the latest version
testImplementation 'org.mockito:mockito-inline:2.13.0'
Related