How to mock Kotlin's List.forEach? - kotlin

For the given code below, in Kotlin, it's not possible to execute the function forEach (or anything similar, map, filter, so on...) because BarList is mocked. So the native implementation of forEach and relatives are not being called. After a bit of search on the internet I came with this:
public class BarList<E> extends AbstractList<E> implements OrderedBarCollection<E> {
//...
}
//...
val mockedList: BarList<Foo> = mockBarList()
val fooList = listOf(Foo())
`when`(mockedList.iterator()).thenReturn(fooList.iterator())
`when`(mockedList.size).thenReturn(fooList.size)
com.nhaarman.mockito_kotlin
.doCallRealMethod()
.`when`(mockedList)
.forEach(Mockito.any<Consumer<Foo>>()) //Attempt to call the Consumer.
mockedList.forEach { foo ->
//Not executing
}
I tried this above based on the answer of this question: https://stackoverflow.com/a/49407513/2430555
I also tried:
com.nhaarman.mockito_kotlin.doCallRealMethod().`when`(mockedList).forEach(any())
But it's causing:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
//...
The definition of forEach in the Kotlin source code is:
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit
I think I should replace any() with something that matches action: (T) -> Unit, but I am not sure how to do this.
I don't mind to use interactor if needed, but I need to at least make forEach run as expected. Could you guys please help me?
Regards,
Pedro

The solution is to use thenAnswer instead of thenReturn for the mocked list.
`when`(mockedList.iterator()).thenAnswer { fooList.iterator() }
Reason:
Author: Tobias Berger
an iterator is only good for going through the list once. Therefore
you usually get a new one every time you call the iterator() function.
If you mock that with thenReturn(messageList.iterator()) , it will
just call that once on messageList and reuse that iterator instance
every time you try to get one for your mock. Once your first loop over
this iterator is finished, it will always say it has no more items.
With thenAnswer you define a supplier that is called each time your
mocked function is used, providing a new iterator for each call (as
would be expected)

I think you cannot mock extension funcitons at all, while they are not members of target class.
forEach is Just outer helper for Iterable
In this case you will be still calling usual forEach of kotlin on fooList.
And i don't understand what is the motivation to mock collections especially substitute iterator of mocking OrderedBarCollection with simple ArrayList (listOf), what is requirement to do it?

Related

How mockk is able to return object wrapped in Result when returnArguments

I am still learning kotlin, and I am curious how is it possible that mockk is able to return some object T wrapped in Result<T>. For better understanding let analyse below example:
We have such method definition
fun save(toSave : Entity): Result<Entity>
when we mock such method using returnArguments like it is done below:
every { mocked.save(any()) } returnsArgument 0
Then method returns Result<Entity>, but logic says that Entity should be returned.
Looking into declaration of returnsArgument there is casting to generic type which in our case is Result<Entity>, but when I tried to do it in plain I had casting exception.
I assume some magic happens inside, but what magic is responsible for such thing?
Would it be done with any wrapping object or it is specific only to Result?
Result<T> is a value class and mockk has a value class support.
After many internal steps returnsArgument will wrap the argument n with the specified value class and will return it.
Would it be done with any wrapping object or it is specific only to Result?
All value classes are supported, not just Result<T>.
// supported
#JvmInline
value class ValueWrapper<out T> (val something: Any?)
// not supported
class SomeWrapper<out T> (val something: Any?)
Hope it helps.

Why is my kotlin hash set not adding elements

I am new to kotlin and I want to make an abstract/open class or interface, something that can be implemented by other classes. Let's call it Test. Now Test needs to have a HashSet (the docs say it requires less memory than a normal set) that every derived class will implement and fill with its own values.
interface Test {
val players: HashSet<String>
}
class Supa: Test {
override val players = hashSetOf<String>()
fun later() {
players.add("new player")
}
}
fun main() {
Supa().later()
println(Supa().players)
}
The above will output []. It seems that for some reason players doesn't get updated. After playing around in the kotlin playground I found out that if I print players from inside later() it will show the added element. Maybe it creates a new instance of player that exists in the scope of the function?? Could someone please show me how I can make an abstract hashSet that the derived class can override and fill with values that stay in the set?
The problem here is that you create two separate instances of Supa. You invoke later() on one of them and then print players of another one. Each Supa() creates a new instance.
You need to store Supa instance inside a variable and use it in both places:
val supa = Supa()
supa.later()
println(supa.players)
This isn't really specific to Kotlin. Your code would work the same in other languages as well.

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.

Initialize new arraylist with (custom) items in one line in Kotlin

In Kotlin I created an extension function to initialise a new ArrayList with custom items, like this:
fun <T> arrayListFrom(vararg item: T): ArrayList<T> {
return item.toMutableList() as ArrayList<T>
}
In this way I can easily create an arraylist like this
arrayListFrom(MyCustomItem(1), MyCustomItem(2))
... without creating a new-empty one, and adding all elements to it one by one
Kotlin has so many useful functions for collections, I cannot imagine I need this extension for easy arrayList initialisation, but couldn't find another simple way. Am I missing out on some useful Kotlin function here?
arrayListOf(items)
So you can just do
arrayListOf(MyCustomItem(1), MyCustomItem(2))
One more easy way to initialize ArrayList not exactly one line.
object: ArrayList<instanceType>() {
init{
add(instance1)
add(instance2)
}
}
Another nifty trick is to leverage Kotlin's basic Array type. Its constructor has an optional init function which allows for cool and simple inits like so val newArray = Array(2) { MyCustomItem(i+1) } which would make [ MyCustomItem(1), MyCustomItem(2) ].
To get an arrayList out of it, just add toCollection(ArrayList()) to the end like so
val newArrayList = Array(2) { MyCustomItem(i+1) }.toCollection(ArrayList())
and presto! The array gets created, and the items get sent to a destination arrayList. You can use the arrayList as needed, and it was done in only one line!
Disclaimer: It's probably slower given the transfer involved under the hood, so use with care of course!

KClass::memberExtensionFunctions always be empty

Code
import kotlin.reflect.full.*
class FooBar(val bar: String)
fun FooBar.baz(): Unit {println(this.bar)}
fun main(args: Array<String>) {
FooBar::class.declaredMemberExtensionFunctions.forEach {
println(it)
}
FooBar::class.memberExtensionFunctions.forEach {
println(it)
}
}
Output is empty
This is because declaredMemberExtensionFunctions only returns extension functions that are declared inside a class (as seen in the docs) and FooBar.baz() is a top level declaration (So it is not declared inside FooBar.
class FooBar(val bar: String) {
fun FooBar.baz(): Unit {
println(this.bar)
}
}
While I imagine this is not what you want, structuring the extension function like this would make your main method output lines.
TLDR: You aren't going to be able to do this. Because extension functions can be declared everywhere, you are limited in what the reflection system can do for you.
There is a thread on kotlinlang.org that covers this exact question and why it is not possible.
Essentially, Kotlin's declaredMemberExtensionFunctions function is able to list extension functions which are declared as part of the class, not externally. The docs state:
Returns extension functions declared in this class.
And of course, memberExtensionFunctions behaves similarly:
Returns extension functions declared in this class and all of its superclasses.
Here's what #Yole says in that thread as to why this is not possible:
The task of finding all extension functions for Foo is equivalent to finding all methods which have Foo as the first parameter. Neither of these is possible without accessing every single class in your application through reflection.
#Yole is on here, he might be able to provide a more authoritative answer for you.