Issue
How to mock or spy some methods but use real logic of another method in the same class using Mockk library?
Here is a simplified logic of parent-child classes that I have:
open class Parent() {
var condition = true
fun method1() {
if (condition) {
method2("bum")
} else {
method3(41)
}
}
fun method2(someStr: String): String {
//some complicated logic
return "some result"
}
fun method3(someInt: Int): Int {
//some complicated logic
return 42
}
}
class Child: Parent() { }
And a test that I want to have:
@Test
fun `when condition is true, it should call method2`() {
clearAllMocks()
val child: Child = mockk()
child.condition = true
every { child.method2(any()) } returns "something"
every { child.method3(any()) } returns 11
child.method1()
verify(exactly = 1) { child.method2(any()) }
}
Of course this logic for testing doesn't work. But how I can call real method1
but mock method2
and method3
?
Solution
The way to mock some methods with Mockk except one:
@Test
fun `when condition is true, it should call method2`() {
clearAllMocks()
val child: Child = spyk()
every { child.condition } returns true
every { child.method2(any()) } returns "something"
every { child.method3(any()) } returns 11
//every { child.method1() } answers { callOriginal() } - this works with and without this line
child.method1()
verify(exactly = 1) { child.method2(any()) }
}
It's possible to do with spyk
and it's obligatory to mock a behavior of methods that need to be mocked with every
.
For non-mocked method add nothing or to be sure that its behavior is unambiguous - you can add callOriginal
Answered By - Alexey Simchenko
Answer Checked By - David Goodson (JavaFixing Volunteer)