mockk fails with function returning List

57 Views Asked by At

I have a function in Class Student.

class Student {
var name: String? = null
var marks: String? = null

fun getMarks():List<String>{
    return listOf<String>("10","10","10")
}
}

I have mocked this class Student and now want to return list of data.

This below test fail with error error

 @Test
    fun test1(){
       val student =  mockk<Student>()
        every { student.getMarks() }.returns(listOf("9","5"))
        student.getMarks()
    }
}
java.lang.IncompatibleClassChangeError: Superclass java.util.List of java.util.List_1_Proxy is an interface (declaration of 'java.util.List_1_Proxy' appears in /data/user/0/com.myapp.mytestapp/app_dxmaker_cache/Generated_-597883428.jar)
1

There are 1 best solutions below

0
user2340612 On

If I try running the test with the exact same code you posted, I get a different error:

io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock

I believe the error message is a bit misleading, and I think the underlying issue is that the generated bytecode effectively contains 2 methods with the same name but different return types:

  • public final String getMarks() { return this.marks; } – generated from the var marks: String? = null property
  • public final List getMarks() { return CollectionsKt.listOf(new String[]{"10", "10", "10"}); } generated from your fun getMarks

If you rename the method for example, I can run it with no issues:

@Test
fun test1() {
    val student = mockk<Student>()
    every { student.getSomeMarks() } returns listOf("9", "5")
    println(student.getSomeMarks())
    Assert.assertEquals(listOf("9", "5"), student.getSomeMarks())
}

which prints [9, 5] and passes successfully.

I think you should strongly consider either renaming the property or the method to disambiguate them, or declaring it as a computed property/override the getter.

Having said that, there might not even be a need to mock the function. Depending on what you want to test, it might be better to use a real object instead of a mock – hard to tell without knowing what the real code is and what you're trying to achieve, though.