0

I am trying to mock MongoCollection class in kotlin

class MyTest {

  val mockCollection: MongoCollection<Document> = mock(MongoCollection<Document>::class.java)

}

it given an error only classes are allowed on the left side of a class literal

on researching a bit I found this only classes are allowed on the left hand side of a class literal I tried create a type for MongoCollection and then passing it to the mock but it gives an error as the mock is of Type.

I also tried casting the mock to Document as below

val mockCollection: MongoCollection<Document> = mock(MongoCollection::class.java) as MongoCollection<Document>

but that gives an NullpointerException exception during access of MongoCollection inside implementation of code.

I have tried both the

and both of them have the same error?

I tired writing the same test in java and casting of generics work in it.

MongoCollection<Document> mockCollection = (MongoCollection<Document>) mock(MongoCollection.class);

Does anyone have any experience of mocking generic classes in Kotlin?

xopehir780
  • 55
  • 6

2 Answers2

0

I wrote the following example for you:

interface Mosi<T> {
    fun mos(): T
}

then all three code snippets below work for testing and test are passed:

class ExampleUnitTest {

    val mosi = Mockito.mock(Mosi::class.java)
    @Test
    fun test() {
        `when`(mosi.mos()).thenReturn("Mosi")
        assertEquals(mosi.mos(), "Mosi")
    }
}
class ExampleUnitTest {

    val mosi = Mockito.mock(Mosi::class.java) as Mosi<String>
    @Test
    fun test() {
        `when`(mosi.mos()).thenReturn("Mosi")
        assertEquals(mosi.mos(), "Mosi")
    }
}
class ExampleUnitTest {

    val mosi = mock<Mosi<String>> {
        on { mos() }
            .thenReturn("Mosi")
    }
    @Test
    fun test() {
        assertEquals(mosi.mos(), "Mosi")
    }
}

if you get NPE the problem is somewhere else, maybe providing more code can help!

Mohsen
  • 1,246
  • 9
  • 22
0

Solution

Create an extension on Mockito like this:

inline fun <reified T: Any> mock() = Mockito.mock(T::class.java)

Usage

Use the extension function like this:

val mockCollection = mock<MongoCollection<Document>>()

val mockCollection: MongoCollection<Document> = mock() // I prefer this one

I always use this instead of the original mock() function since the java class can be inferred. Saves some typing.

Off-topic

It's even great for mocking Lambdas!

val callback: () -> Unit = mock()

someClass.doSomething(callback)

verify(callback).invoke()
Darryl Johnson
  • 646
  • 6
  • 14