mockk icon indicating copy to clipboard operation
mockk copied to clipboard

Stubbing a method on a spyk object calls the original method immediately.

Open pikaboo opened this issue 4 years ago • 14 comments

Expected Behavior.

When stubbing a method on a spyk the method is invoked only when it is invoked from outside, by another object that is using the spy

Current Behavior

When the method is stubbed, it is immediately invoked, and it invokes the original one not the stubbed one, and even worse this behaviour is unexpected, meaning sometimes it does behave as expected and most of the time it does not.

Failure Information (for bugs)

for example the method

   class SomeClass() {
       fun login(listener: (Boolean) -> Unit ) {
            do some async logic and then call the listener with the result
      }
   }


   val spy = spyk(SomeClass())  {

          val completion = slot<(Boolean) -> Unit>()
         //this immediately calls the original login method
         every { login(capture(completion)) } answers {
              completion.captured.invoke(true)
         }
     }

Context

Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

  • MockK version: 1.10.0
  • OS: Android 29
  • Kotlin version: 1.3.61
  • JDK version: 8
  • JUnit version: 4.12
  • Type of test: instrumented

pikaboo avatar Jun 11 '20 17:06 pikaboo

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. If you are sure that this issue is important and should not be marked as stale just ask to put an important label.

stale[bot] avatar Aug 11 '20 05:08 stale[bot]

issue not stale

pikaboo avatar Aug 11 '20 19:08 pikaboo

I've encountered that issue, my situation was as follows: mockk version mockk:1.10.0 had two test functions using exact same code, something like: ` @Test fun func1(){ val parser = MyParser() val mock = spyk(parser, recordPrivateCalls = true) every { mock invoke "getDivider" withArguments listOf(any()) } returns 0L // Some code parser.parse() }

@Test fun func2(){ val parser = MyParser() val mock = spyk(parser, recordPrivateCalls = true) every { mock invoke "getDivider" withArguments listOf(any()) } returns 0L // Some other code parser.parse() }`

surprisingly func1 executed the actual 'getDivider' method while func2 mocked the result without running the actual code

mishael-w avatar Aug 25 '20 16:08 mishael-w

Do you run those tests one after the other or one by one ?

pikaboo avatar Aug 26 '20 14:08 pikaboo

I ran those tests separately

mishael-w avatar Aug 26 '20 14:08 mishael-w

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. If you are sure that this issue is important and should not be marked as stale just ask to put an important label.

stale[bot] avatar Oct 25 '20 14:10 stale[bot]

issue note stale

pikaboo avatar Oct 27 '20 19:10 pikaboo

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. If you are sure that this issue is important and should not be marked as stale just ask to put an important label.

stale[bot] avatar Dec 26 '20 23:12 stale[bot]

Running into the same issue.

daespark avatar May 14 '21 22:05 daespark

This is also true for Kotlin classes that have @JvmStatic functions. pretty sucky because we can't really do

mockkStatic(NavHostFragment::class)
every { NavHostFragment.findNavController(ofType(Fragment::class)) } returns mockNavController

this invokes the NavHostFragment::findNavController and we end up getting exception on the latest Navigation Api

daespark avatar Oct 20 '21 18:10 daespark

I'm having the same issue when trying to stub a @JvmStatic function on a Kotlin singleton object with mockkObject. This is really confusing, because it already takes quite a while to actually find that the method is called when it should be stubbed, and then you're still no bit closer to work around this while still being able to stub the functionality you need.

Mockk 1.12.2 Kotlin 1.5.20

fblampe avatar Mar 04 '22 13:03 fblampe

Same problem with Spring and springmockk @SpykBean:

@SpykBean
private lateinit var service: MyService

@Test
fun `capturing a parameter of a secured function call`() {
        val pageable = slot<Pageable>()
        verify { service.securedCall(capture(pageable)) }
}

ends up in a Spring Security Exception as the verify does a real function call. (Kotlin 1.9.10, Mockk 1.13.8)

aburmeis avatar Jan 12 '24 11:01 aburmeis

Is there any update on this?

RotBolt avatar Apr 05 '24 05:04 RotBolt