sorry, i cant really answer you question, but i have learned some bad lessons with kotlin and mocking:
in my case i needed to mock an interface (what i would have suggested you to do), just as used to from regular OOP. the kotlin way of specifying a class' type but then returns a null value (fun javaClass(): Class<T> = null as Class<T>) when it comes to using matchers, which will make your mock framework (mockito in my case) fail. so no proper mocking in kotlin ATM, still need to use java/groovy/whatever when it comes to testing :(
There's no way to mock top-level functions in the clasical sense. They are analogous to (and compiled to) static functions in Java, so when you want classical mocking, you should refrain using them.
What you can do, though, is abstract whatever external dependencies you top-level function has as parameters of functional types, and “inject” them in your tests:
fun sumWithRandom(
// normal parameter
num: Long,
// injected function dependency, default value corresponds to the standard behavior
randomInt: (Long, Long) -> Long = ::getRandomInt
): Long {
return num + randomInt(1, 10)
}
Then, in your test you can say:
assertEquals(43, sumWithRandom(42, { min, max -> min}))
Today it’s basically impossible to have a functional project (only model definition as classes) as you could have in other FP languages, such as clojure
To me, a perfectly functional project never needs any kind of mocking. If your function depends on some logic that differs between production code and tests, pass that logic as a parameter of a function type, as in Andrey’s example above.
@yole in a perfectly functional project we may still need to verify that a function were called with a set of specific arguments. For that, mockito’s spies are useful, which are form of mocks.