How to mock lambda with mockito in kotlin - kotlin

I have a kotlin Android app. There is a function that loads compositions from the backend and returns them to a callback:
getCompositons(callback: (Array<Composition>) -> Unit)
How can I mock the callback using mockito. So that I then can do something like this:
var callback = //mockito mock
getCompositons(callback)
verify(callback, timeout(10000)).apply()
I read that lambda are matched to the java type function and therefore I assume apply could be the method invoked. Maybe I could mock a function and use that? But the Kotlin function interface only seems to have one return type, no parameters. java.util.Function says unresolved reference function.
Any help appreciated.

This is really no different to mocking any other type:
val callback = mock<(Array<Composition>) -> Unit>()
getCompositons(callback)
verify(callback)(any()) // Or verify(callback).invoke(any()) to be explicit
(In case you weren't aware of them, I'm using the mockito-kotlin bindings here.)

You can do that like this:
val function: Array<Composition>) -> Unit = {}
val callback = mock(function::class.java)
getCompositons(callback)
verify(callback)(any()) // or for example verifyNoInteractions(callback)
No extra libraries besides the standard mockito are needed

I solved here mocking the callback like this:
private val onNewUrl: (url: String) -> Boolean = mock {
on { mock(any()) } doReturn true
}
verify(onNewUrl).invoke(any())

Related

Using Kotlin's extension function to suppress a returned value

I am using Kotlin in a spring boot application. Especially in the services, I have found that some of the function need to suppress the returned value from repository. For example, here is a save() that saves an entity without returning the persisted entity id:
fun save(person: Person) {
personRepository.save(person)
}
As you can see that this function simply delegates the call to the JpaRepository#save(...) and does not return anything. What I wanted to do was something like this:
fun save(person: Person) = personRepository.save(person)
In order to do this, I have created an extension function:
fun Any.ignoreReturn() = Unit
and then make the call to the `personRepository#save(...) as:
fun save(person: Person) = personRepository.save(person).ignoreReturn()
What I wanted to know was:
Is this the right way to do it?
Are there side effects to such extension function as I am extending Any?
One way could be to do it like this:
fun save(person: Person): Unit = let { personRepository.save(person) }
Important part there is to declare the function to return Unit so the generated code from let wont need to return what personRepository.save(person) is returning. You can test it, just remove : Unit part and you get different signature for your save function.

unit testing extension function and mocking the other methods of the class

I am writing an extension function adding some retry capabilities to AmazonKinesis.putRecords. In my extension method i do some logic and some calls to the original putRecords method:
fun AmazonKinesis.putRecordsWithRetry(records: List<PutRecordsRequestEntry>, streamName: String) {
//...
val putRecordResult = this.putRecords(PutRecordsRequest().withStreamName(streamName).withRecords(records))
//...
}
From a unit test point of view I am finding it hard to see how I should mock the call to this.putRecords
I am using com.nhaarman.mockitokotlin2.*
val successfulRequest = PutRecordsResultEntry().withErrorCode(null);
class KinesisExtensionTest : StringSpec({
val testRecords = ArrayList<PutRecordsRequestEntry>()
testRecords.add(PutRecordsRequestEntry().withPartitionKey("iAmABunny").withData(ByteBuffer.wrap("aaa".toByteArray()))
)
val kinesis = mock<AmazonKinesis>{
on { putRecordsWithRetry(testRecords, "/dev/null") }.thenCallRealMethod()
on { putRecords(any()) }.thenReturn(PutRecordsResult().withRecords(listOf(successfulRequest, successfulRequest)))
}
"can write a record" {
kinesis.putRecordsWithRetry(testRecords, "/dev/null")
verify(kinesis).putRecord(any())
}
})
The putRecordResult is always null
The extension function AmazonKinesis.putRecordsWithRetry will be compiled to a static function under the hood, and Mockito doesn't support static method mocking yet.
Therefore Mockito may not know the stubbing information at the verification step and thus the default null value is produced.

Can Mockito be used to match parameters that are functions in Kotlin?

I have a function with a prototype similar to:
class objectToMock {
fun myFunc(stringArg: String, booleanArg: Boolean = false, functionArg: (String) -> Any = { 0 }): String
}
I'd like to be able to stub myFunc but can't figure out how to. Something like
#Mock
lateinit var mockedObject: ObjectToMock
#Before
fun setup() {
MockitoAnnotations.initMocks(this)
`when`(mockedObject.myFunc(anyString(), anyBoolean(), any())).thenReturn("")
}
Using any() and notNull() both lead to java.lang.IllegalStateException: any() must not be null
The solution here is to use anyOrNull from https://github.com/nhaarman/mockito-kotlin, or implement that helper yourself.
Mockito often returns null when calling methods like any(), eq() etcetera. Passing these instances to methods that are not properly mocked, can cause NullPointerExceptions
see: https://github.com/nhaarman/mockito-kotlin/wiki/Parameter-specified-as-non-null-is-null
you can add
mockedObject = ObjectToMock()
#Before It is the place to initialize.
#Test It is the place to test.you can call mockedObject.myFunc()

Possible to keep `Unit` as the return type of a Kotlin function when called from Java?

I have a kotlin function inside a sealed class.
fun invoke(callback: Callback): Unit
Java sees the method signature as a function that returns void.
Is it possible to instruct the Kotlin compiler to keep Unit as the return type for Java? (not void)
Use case
My use case is a jvm interop issue from Java where I need to implement (Result) -> Unit.
// inside a java method (currently)
abstractClass.invoke(callback)
return Unit.INSTANCE
// what I'd prefer instead
return abstractClass.invoke(callback) // invoke returns Unit, but it's in Kotlin, so it maps to void in Java. So this doesn't work
For your edge case, you'd still have to deal with Java methods returning void. So just solve it once:
fun <T> fromConsumer(consumer: Consumer<T>): (T) -> Unit = { consumer.consume(it) }
and then instead of implementing (Result) -> Unit directly, implement/create a Consumer<Result> and pass it to this function. It could be written in Java as well, just would be more complicated.
It would certainly be possible to do this in Java:
public kotlin.Unit test() { return null; }
But in Kotlin your best option seems to be to go with a function object:
val invoke: (Callback) -> Unit = {}
// from Java:
return abstractClass.getInvoke(callback)
I may have misunderstood your question.
First, in Kotlin,
fun invoke(callback: Callback): Unit
is equivalent to
fun invoke(callback: Callback)
In Java, if you override a function like that, you do not need to return anything.
Is it possible to instruct the Kotlin compiler to keep Unit as the return type for Java? (not void)
No, because Unit is meaningless. The only valid value of Unit is Unit itself.

Getting access to an instance in a wrapper function

In Kotlin I have this function to wrap a transaction:
fun wrapInTransaction(code: () -> Unit) {
realmInstance.beginTransaction();
code.invoke()
realmInstance.commitTransaction();
}
How can I get access to realmInstance in the invoked code?
The easy solution here is to make code a function with receiver:
fun wrapInTransaction(code: Realm.() -> Unit) {
realmInstance.beginTransaction();
realmInstance.code()
realmInstance.commitTransaction();
}
Inside a lambda which you pass as code you will be able to use this to reference the RealmInstance and to use its members directly as if inside a member function.
Calling realmInstance.code() is just calling code with passing realmInstance as a receiver to it.
The other answers correctly demonstrate how to pass the RealmInstance object to the lambda. In addition, you can make the whole function an extension function which makes the call site a bit prettier:
fun Realm.wrapInTransaction(code: Realm.() -> Unit) {
//this is implicit
beginTransaction();
code()
commitTransaction();
}
The call site will look like this:
Realm.getInstance(this).wrapInTransaction {
createObject(User.class)
}
Change the wrapInTransaction function to accept an extensions method on realmInstance like so:
fun wrapInTransaction(code:Realm.() -> Unit){
realmInstance.beginTransaction();
realmInstance.code()
realmInstance.commitTransaction();
}
Then you can use it like:
wrapInTransaction {
println("realm instance is $this, instanceId: $instanceId")
}
Where for the sake of the example the Realm looks like:
class Realm {
val instanceId = 42
fun beginTransaction() {
}
fun commitTransaction() {
}
}
The above technique is possible thanks to Kotlin's Function Literals with Receiver that make it possible to set the this instance (receiver) within lambda function body. It makes it easy to build type safe builders that reassemble ones from Groovy or Ruby.
This answer provides more samples on the technique.