MockK spy on top-level private function in Kotlin - kotlin

I need to verify if bar function is called or not using MockK library.
MyFile.kt
fun foo() {
bar()
}
private fun bar() { ... }
How can I mock the 'bar' function?
I am trying the following.
#Test
fun test() {
mockkStatic("com.mypkg.MyFileKt")
every { bar() } returns Unit
foo()
verify(exactly = 1) { bar() }
}
This gives compile-time error: Cannot access 'bar': it is private in file.
It works fine if I make the bar function internal. Probably I will have to spy on it but cannot find an example to do that.

Although I don't think it's a good idea to mock private methods, since they should most likely be tested in conjunction with the method calling them, MockK does support this:
https://mockk.io/#private-functions-mocking--dynamic-calls
So your code would look something like this:
class TheClass {
fun foo() {
bar()
}
private fun bar() {}
}
#Test
fun theTest() {
val mock = spyk<TheClass>(recordPrivateCalls = true)
every { mock["bar"]() } returns Unit
mock.foo()
verify(exactly = 1) { mock["bar"]() }
}

Related

Kotlin like scope functions (let, also, apply, run) in Groovy

I think the title speaks for itself - does Groovy have something like Kotlin scope functions?
obj.apply {
foo()
bar()
baz()
}
// is the same as
obj.foo()
obj.bar()
obj.baz()
Groovy has obj.with { } method that allows you to do the same:
obj.with {
foo()
bar()
baz()
}
There is also obj.tap { } variant (an equivalent of obj.with(true) { }) that does the same, but it returns the incoming object.
def newObj = obj.tap {
foo()
bar()
baz()
}
Source: http://docs.groovy-lang.org/docs/next/html/documentation/style-guide.html#_using_with_and_tap_for_repeated_operations_on_the_same_bean

Mockito: How to mock lambda callback? what is the type? (Kotlin)

I have two class TestTarget, MockTarget and test code below. If the TestTarget has two functions with same name and same count of parameter, the any() is ambiguous. I need to assign the type to any(ClassType). But what is the type of () -> Unit? I have tried Function0 and it doesn't work. Can anyone help?
Class TestTarget:
Class TestTarget(private val mockTarget: MockTarget) {
fun testFunction() {
// some logic to be tested.
// call mockTarget.doSomething.
}
}
Class MockTarget
Class MockTarget {
fun doSomething(callback: () -> Unit) {
// some logic here.
}
fun doSomething(listener: OtherType) {
// Test code works without this function.
}
}
Test Code:
// setup mocks.
#Test
fun `verify testFunction`() {
`when`(mockTarget.doSomething(any())).thenAnswer { invocation ->
// callback here.
}
}
Replace org.mockito.Mockito with org.mockito.kotlin.*
and you can code like this
val anyLambda = any<() -> Unit>()
val anyListener = any<OtherType>()

"Property must be initialized or be abstract" in init block when throwing an exception

Why does kotlin report Property must be initialized or be abstract. The object construction is never finished, so it should not matter whether a is initialized or not. Could a case be demonstrated where this would be a problem?
class Foo {
private val a: Int
init {
a = 42
throw Exception()
}
}
fun main() {
Foo()
}
kotlin playground
However these work just fine
fun bar() {
throw Exception()
}
class Foo {
private val a: Int
init {
a = 42
bar()
}
}
fun main() {
Foo()
}
kotlin playground
class Foo {
private val a: Int = throw Exception()
}
fun main() {
Foo()
}
kotlin playground
Similar java code works as expected:
public class Test {
private static class Foo {
private final int a;
public Foo() throws Exception {
a = 42;
throw new Exception();
}
}
public static void main(String []args) throws Exception {
new Foo();
}
}
The question is very well answered in the below link.
Kotlin: why do I need to initialize a var with custom getter?
Essentially it boils down to having a backing field for every "val" (property) . If you can provide a backing field, you need not initialize the field. Below is a small example of it.
class Foo {
private val a: Int
get() = getValue()
}
fun getValue():Int {
throw Exception()
}
fun main() {
Foo()
}
Similar java code works as expected:
Java initializes fields to 0 (or null/false depending on type) by default. You can see it e.g. by printing a's value before the a = 42 line.
Kotlin doesn't, because this implicit initialization makes it too easy to forget to initialize a property and doesn't provide much benefit. So it requires you to initialize all properties which have backing fields.
It seems to be a compiler bug as Alexey suggested
There is similar issue posted on Kotlin bug tracer.

How to mock and verify Lambda expression in Kotlin?

In Kotlin (and Java 8) we can use Lambda expression to remove boilerplate callback interface. For example,
data class Profile(val name: String)
interface ProfileCallback {
fun onSuccess(profile: Profile)
}
class ProfileRepository(val callback: ProfileCallback) {
fun getProfile() {
// do calculation
callback.onSuccess(Profile("name"))
}
}
We can change remove ProfileCallback and change it into Kotlin's Lambda:
class ProfileRepository(val callback: (Profile) -> Unit) {
fun getProfile() {
// do calculation
callback(Profile("name"))
}
}
This works fine, but I'm not sure how to mock and then verify that function. I have
tried using Mockito like this
#Mock
lateinit var profileCallback: (Profile) -> Unit
#Test
fun test() {
// this wouldn't work
Mockito.verify(profileCallback).invoke(any())
}
but it throw an Exception:
org.mockito.exceptions.base.MockitoException: ClassCastException
occurred while creating the mockito mock : class to mock :
'kotlin.jvm.functions.Function1', loaded by classloader :
'sun.misc.Launcher$AppClassLoader#7852e922'
How to mock and verify Lambda expression in Kotlin? Is it even possible?
Here is example how you can achieve that using mockito-kotlin:
Given repository class
class ProfileRepository(val callback: (Int) -> Unit) {
fun getProfile() {
// do calculation
callback(1)
}
}
Using mockito-kotlin lib - you can write test mocking lambdas like this:
#Test
fun test() {
val callbackMock: (Int) -> Unit = mock()
val profileRepository = ProfileRepository(callbackMock)
profileRepository.getProfile()
argumentCaptor<Int>().apply {
verify(callbackMock, times(1)).invoke(capture())
assertEquals(1, firstValue)
}
}

Method References to Super Class Method

How to use method references to refer to super class methods?
In Java 8 you can do SubClass.super::method.
What would be the syntax in Kotlin?
Looking forward to your response!
Conclusion
Thanks to Bernard Rocha!
The syntax is SubClass::method.
But be careful. In my case the subclass was a generic class. Don't forget to declare it as those:
MySubMap<K, V>::method.
EDIT
It still doesn't work in Kotlin.
Hers's an example in Java 8 of a method reference to a super class method:
public abstract class SuperClass {
void method() {
System.out.println("superclass method()");
}
}
public class SubClass extends SuperClass {
#Override
void method() {
Runnable superMethodL = () -> super.method();
Runnable superMethodMR = SubClass.super::method;
}
}
I'm still not able to do the same in Kotlin...
EDIT
This is an example how I tried to achieve it in Kotlin:
open class Bar {
open fun getString(): String = "Hello"
}
class Foo : Bar() {
fun testFunction(action: () -> String): String = action()
override fun getString(): String {
//this will throw an StackOverflow error, since it will continuously call 'Foo.getString()'
return testFunction(this::getString)
}
}
I want to have something like that:
...
override fun getString(): String {
//this should call 'Bar.getString' only once. No StackOverflow error should happen.
return testFunction(super::getString)
}
...
Conclusion
It's not possible to do so in Kotlin yet.
I submitted a feature report. It can be found here: KT-21103 Method Reference to Super Class Method
As the documentation says you use it like in java:
If we need to use a member of a class, or an extension function, it
needs to be qualified. e.g. String::toCharArray gives us an extension
function for type String: String.() -> CharArray.
EDIT
I think you can achieve what you want doing something like this:
open class SuperClass {
companion object {
fun getMyString(): String {
return "Hello"
}
}
}
class SubClass : SuperClass() {
fun getMyAwesomeString(): String {
val reference = SuperClass.Companion
return testFunction(reference::getMyString)
}
private fun testFunction(s: KFunction0<String>): String {
return s.invoke()
}
}
Don't know if it is possible to get the reference to super class's function, but here is an alternative to what you want to achieve:
override fun getString(): String = testFunction { super.getString() }
According to Bernardo's answer, you might have something like this. It doesn't have remarkable changes.
fun methodInActivity() {
runOnUiThread(this::config)
}
fun config(){
}
What is more, in the incoming 1.2 version you can use just
::config