Issue
I am aware of duplicate, bo no answer about actual question was given there.
How to verify if method is called on System under test (not a mock)
I have a class:
class A {
public long a() {
if(something) {
return quicklyCalculatedResult
} else {
return b() run on separate thread, with this one blocked
}
}
public long b() {} //doStuffOnCurrentThread;
}
I have a complete set of tests for b(), which does the heavy lifting. Unfortunately I have to make an ugly think like a() (legacy code) and I don't want to copy all the tests. Of method b(). Also, both of these need to be public.
I want to verify that under certain circumstances a() calls b(), but I cannot do that, beacause tested class is not a mock. I need a way to verify that method was called on a real object, not only a mock.
Solution
Mockito and other kotlin mocking libraries provide partial mocking or similar functionality. You can specify real methods to be called, while the other methods remain stubs:
Mockito java example:
A classUnderTest = mock(A.class);
when(classUnderTest.a()).thenCallRealMethod();
classUnderTest.a();
verify(classUnderTest).b()
See the mockito Documentation on partial mocking. Partial mocking is not encouraged because it does not fit good OOP design, but in your case it fit its intended purpose, which is to test difficult legacy code.
Kotlin example with vanilla Mockito:
val classUnderTest = mock(A::class.java)
`when`(classUnderTest.a()).thenCallRealMethod()
classUnderTest.a()
verify(classUnderTest).b()
mockito-kotlin provides extensions that allow you to use mockito in a more kotlin idiomatic way. Unfortunately there does not appear to be a way to do partial mocking in a kotlin idiomatic way, but it can be achieved in mockito-kotlin like so:
val classUnderTest = mock<A>()
doCallRealMethod().whenever(classUnderTest).a()
classUnderTest.a()
verify(classUnderTest).b()
MockK, an idiomatic kotlin mocking library, allows for this functionality with spys. After creating a spy
of the class you can choose to stub methods:
val classUnderTest = spyk<A>()
every { classUnderTest.b() } returns 1L
classUnderTest.a()
verify { classUnderTest.b() }
Answered By - Dean
Answer Checked By - Candace Johnson (JavaFixing Volunteer)