Mockk: How to mock object id being generated when object is saved (answers + vararg)

1.4k views Asked by At

In my test I need to mock a situation, when new object is saved into database using entity manager (em) and during that process, id property of that object is set to auto-incremented id of that row in database. I would like to set that id property to my own value that I could match later in the test.

I'm using mockk 1.9.3 and kotlin 1.4.0.

So far I have this:

val myVal = 123

every { 
     em.persist(any<MyObj>()) 
} answers {
     firstArg<MyObj>().id = myVal
     // return of the persist method
     em
}

Edit: The em.persist method looks like this, problem is probably related to first argument being vararg.

open fun persist(vararg o: Any?): T {
    o.forEach { doThePersist(it) }
    return this as T
}

But when I try to run that code, I get:

java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class MyObj

Looks like the problem is in the firstArg call. If I place a breakpoint on that line, it will reach it and stop there, the exception occurs when I try to evaluate firstArg<MyObj>().

In documentation I was able to find only example using simple Int or example on how to match varargs. Any ideas why the ClassCastException is thrown or how to handle the varargs properly in answers section?

1

There are 1 answers

0
Aleš Zrak On BEST ANSWER

As Михаил Нафталь pointed out in his comment, if the mocked method uses varargs, the arguments are passed into answers lambda as an array in the first argument. This solution works for my case:

val myVal = 123

every { 
     em.persist(any<MyObj>()) 
} answers {
     val myObj = firstArg<Array<*>>()[0].id as MyObj
     myObj.id = myVal
     // return of the persist method
     em
}

I don't have to use special matcher for varargs in every section, as I need to match only the first argument in my case.

Maybe there is more elegant way of handling varargs in the answers section, but I was not able to find any in the docs. Improvement tips welcome :)