How to verify whether a function is called on a mock object who parameter has a lambda expression - kotlin

Let's say I've a function named
fun doSomething() {
customObject.callThis(10, 20)
}
And customObject is an object of class CustomObject and it's mocked using Mockito. The below is the Unit test one will write for the above code.
#Test
fun doSomething() {
// Call the doSomething() function
verify(customObject).callThis(10, 20)
}
This works perfectly. Now my doubt comes when we write doSomething function as below.
fun doSomething() {
customObject.callThis(10, { navigation.finish() })
}
Where navigation is a mock object of class Navigation. Now, how do I test the above function?

If you are using mockito-kotlin, you could do something like the following:
import com.nhaarman.mockitokotlin2.inOrder
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.any
inOrder {
verify(customObject).callThis(eq(10), any())
verify(navigation).finish()
}

Related

How can Mockito mock a Kotlin `use` (aka try-with-resource)?

If I were trying to add mocks to the following code (where the MyTypeBuilder is mocked to return a mocked MyType - which implements Closeable):
myTypeBuilder.build(myTypeConfiguration).use { myType ->
myType.callMyMethod()
}
Then trying to verify interactions with myType.callMethod() something like:
myType: MyType = mock()
myTypeBuilder: MyTypeBuilder = mock()
whenever(myTypeBuilder.build(any())).thenReturn(myType)
doMethodCall()
verify(myType, times(1)).callMyMethod()
I'm getting errors:
Wanted but not invoked:
myType.callMethod()
-> at package.me.MyType.callMyMethod(MyType.kt:123)
However, there was exactly 1 interaction with this mock:
myType.close()
-> at kotlin.io.CloseableKt.closeFinally(Closeable.kt:57)
So it appears that I need to add a whenever to execute the use block, but I'm not sure what that should look like. Alternatively, the use should act like a Mockito spy rather than a mock, but then allow mocking on the other methods.
I tried to reconstruct the error by writing the following code which is basically what you wrote in your question plus some println statements and some boilerplate to make it runnable:
import org.junit.jupiter.api.Test
import org.mockito.Mockito.*
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import java.io.Closeable
open class MyTypeBuilder {
open fun build(config: Any): MyType {
println("build")
return MyType()
}
}
open class MyType : Closeable {
fun callMyMethod() {
println("callMyMethod")
}
override fun close() {
println("close")
}
}
val myTypeConfiguration: Any = "heyho"
fun call(myTypeBuilder: MyTypeBuilder) {
myTypeBuilder.build(myTypeConfiguration).use { myType ->
println("call")
myType.callMyMethod()
}
}
class MockAndUseTest {
#Test
fun test() {
val myType: MyType = mock()
val myTypeBuilder: MyTypeBuilder = mock()
whenever(myTypeBuilder.build(any())).thenReturn(myType)
call(myTypeBuilder)
verify(myType, times(1)).callMyMethod()
}
}
When I run the test case test, it succeeds and is green.
So, unfortunately whatever may cause your problem, it is not contained in the details given by your question.

MockK spy on top-level private function in 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"]() }
}

Equivalent of doReturn(x).when(y)... in mockk?

I am looking for a mockk equivalent of doReturn(...).when(...).*
I am working on writing some unit tests (testing contracts) that involves a lot of system classes and so need to intercept the methods that I don't control and return some call backs (which the method in code would have eventually returned). In mockito, I could do something like doReturn(...).when(...).*
I Wasn't able to find a similar thing in mockK. Seems like every{} always runs the block before answers or returns.
class Vehicle: Listener {
fun displayCar(listener:Listener){
OtherClass().fetchCar(listener)
}
override fun showCarSuccessful() {
//do something
}
}
class OtherClass {
//assume its an outside function that returns nothing but invokes a method of listener call back
fun fetchCar(listener: Listener) {
//... Some system level operations that I don't have control to generate mock objects but in the test I want to use the listener to call some method so that I can
// test some contracts
listener.showCarSuccessful()
}
}
class Tests {
#Test
fun testCarSuccess() {
val listener: Listener = mockk(relaxed = true)
val vehicle = Vehicle()
//also tried with mockkClass and others
val other: OtherClass = mockk(relaxed = true)
every { other.fetchCar(listener) } returns {listener.showCarSuccessful()}
vehicle.displayCar(listener)
//do some verification checks here
}
}
interface Listener {
fun showCarSuccessful()
}
The every{} block is your when clause. You can set up multiple conditions for returning different results. See the example of setting up fixed returns and performing progrommatic answers
import io.mockk.MockKException
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class MyClass {
fun add(operand1: Int, operand2: Int): Int {
TODO()
}
}
class MockkTest {
#Test
fun testMocking() {
val myClassMock = mockk<MyClass> {
every { add(1, 2) } returns 3 // Set behaviour
every { add(2, 2) } returns 4 // Set behaviour
every { add(3, 4)} answers {args[0] as Int * args[1] as Int} // Programmatic behaviour
}
Assertions.assertEquals(3, myClassMock.add(1, 2))
Assertions.assertEquals(4, myClassMock.add(2, 2))
Assertions.assertEquals(12, myClassMock.add(3, 4))
Assertions.assertThrows(MockKException::class.java) {
myClassMock.add(5, 6) // This behaviour has not been set up.
}
}
}
But, in your example in particular, I find this line:
every { other.fetchCar(listener) } returns listener.showCarSuccessful()
very strange. First it is not doing what you think it is doing - it is going to make that call as you set this behaviour up you are telling your mock to return the result of that call, not to do that cal. To do what you want to do, you should rather do this:
every { other.fetchCar(listener) } answers {listener.showCarSuccessful()}
But even then, this line is setting up the mock behaviour after you have called your class under test - set up your mock behaviour first.
Also, it is strange that you are setting up side effects in a top level mock in a nested mock. Surely for testing your Vehicle class all you want to do is verify that its inner class was called with the correct arguments. Also, how does Vehicle get a reference to your OtherClass mock, it is instantiating a new one and calling that function.
Here is an attempt to make your example work:
import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.Test
interface Listener {
fun showCarSuccessful()
}
class Vehicle(val other: OtherClass) : Listener {
fun displayCar(listener: Listener) {
other.fetchCar(listener)
}
override fun showCarSuccessful() {
//do something
}
}
class OtherClass {
//assume its an outside function that returns nothing but invokes a method of listener call back
fun fetchCar(listener: Listener) {
}
}
class VehicleTest{
#Test
fun testDisplayCar(){
val listener: Listener = mockk(relaxed = true)
val other: OtherClass = mockk(relaxed = true) //also tried with mockkClass and others
val vehicle = Vehicle(other)
vehicle.displayCar(listener)
verify{ other.fetchCar(listener) }
}
}
Even this I think is maybe still a bit off - I suspect that the listener you want Vehicle to pass to OtherClass is itself, not an argument...
You should also then write a separate test for OtherClass to make sure it does what you expect it to when you call fetchCar

How mock Kotlin extension function in interface?

I have an extension function for interface like the following:
import javax.jms.ConnectionFactory
fun ConnectionFactory.foo() {
println("do some stuff")
}
How can I mock the function foo?
Please note, I have seen approaches for classes and objects in http://mockk.io/#extension-functions, but it does not work. I have tried this one:
import io.mockk.classMockk
import io.mockk.every
import org.junit.Test
import javax.jms.ConnectionFactory
class ExtensionFunctionTest {
#Test
fun mockExtensionFunction() {
val connectionFactory = classMockk(ConnectionFactory::class)
every { connectionFactory.foo() } returns println("do other stuff")
connectionFactory.foo()
}
}
It throws exception:
io.mockk.MockKException: Missing calls inside every { ... } block.
According to the documentation in case of module wide extension functions you need to staticMock "hidden" class created for an extension function.
Here is an example (assuming the file name is com/sample/extmockingtest/SampleTest.kt):
fun <T> Iterable<T>.foo(): String = "do some stuff"
class ExtensionFunctionTest {
#Test
fun mockExtensionFunction() {
val itMock = classMockk(Iterable::class);
staticMockk("com.sample.extmockingtest.SampleTestKt").use {
every {
itMock.foo()
} returns "do other stuff"
assertEquals("do other stuff", itMock.foo())
verify {
itMock.foo()
}
}
}
}

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