7

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.

Ashwin
  • 7,277
  • 1
  • 48
  • 70
  • 1
    Is it an idea to verify the things which happen inside bar()? At least that is imho what should be tested instead of the method call or there is potential to refactor something in order to avoid spying. What do you think @ashwin I was thinking about this and thought that depending what happens inside bar() it should be refactored to an extract class respecting SRP https://anthonysciamanna.com/2016/02/14/should-private-methods-be-tested.html – Robin Vinzenz Feb 19 '21 at 11:27
  • 1
    @RobinVinzenz You are right, I will have to refactor this; maybe MockK does not support spying/mocking top-level private functions. – Ashwin Feb 20 '21 at 12:19

1 Answers1

4

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"]() }
}
Erik Finnman
  • 1,459
  • 18
  • 25
  • 2
    This will work, I just wanted to know whether MockK can mock/spy a Kotlin top-level private function. – Ashwin Feb 19 '21 at 17:35
  • As far as I can tell, it seems only possible to mock top level functions like you have already done. – Erik Finnman Feb 22 '21 at 07:59
  • This is just bullcr*p. Changing method name will make you cry all day. Mockk shouldn't have allowed it at all or should have made some reliable API for such a case – Farid Nov 16 '21 at 18:57
  • Make sure not to miss the () like I did after mock["bar"] otherwise you will get a Type mismatch, Required: MockKMatcherScope.DynamicCall. – Eric Feb 24 '23 at 21:31