beatrice
beatrice

Reputation: 4391

Real method getting called while setting up mock on spy

It is driving me crazy why the real method getting called during setting up the mock on spy.

@Service
class A(){

 fun someMethod():String{
  println("inside real method")
  return "result"
 } 
}

test:

@SpyBean
private lateinit var a:A

@Test
fun test(){
 println("before mock")
 Mockito.`when`(a.someMethod()).doReturn("mock_result")
 println("empty test ended")
}

result:

before mock
inside real method
empty test ended

Once change from Sypbean to Mockbean then it works as expected:

@MockBean
private lateinit var a:A

@Test
fun test(){
 println("before mock")
 Mockito.`when`(a.someMethod()).doReturn("mock_result")
 println("empty test ended")
}

result:

before mock
empty test ended

Why the real method getting called while just setting up the mock? There is no direct method invocation at all in the code, the real test not even started.

edit: I tried with doReturn,thenReturn,doAnswer,thenAnswer , the result is the same: if it is a spy then the real method getting called in the initializing phase

Upvotes: 1

Views: 2010

Answers (2)

My 2 cents: I fell into the same problem. The mocking worked well on Java classes, but did not work well (as described above) on Kotlin classes. I found that both, the class being mocked, and the method being mocked MUST be explicitly marked as "open". Then the mocking works as expected (both variants of the "when" statement work OK).

open class ToBeMocked {
    open fun toBeMocked() {} // The "open" keyword here is crucial
}

Upvotes: 0

dey
dey

Reputation: 3140

As you mentioned in the comments, the answer from here helped: Mockito: Trying to spy on method is calling the original method

Explanation:

Having this line of code:

`when`(a.someMethod()).doReturn("mock_result")`

The code is executed in that way:

  1. execute a.someMethod()
  2. pass return value to when() method

But mockito is making his "magic" (I'm not aware of implementation details), to stub the next call of this method. But you already called the real method when stubbing.

That's why using different way of stubbing is not making this effect:

doReturn("mock_result").`when`(a).someMethod()

In This case, you are not calling a.someMethod(), but you tell mockito that it has to return "mock_result" when someMethod() is called.

Upvotes: 1

Related Questions