MockK如何在Kotlin中对顶级私有函数进行间谍测试

7
我需要使用MockK库来验证是否调用了bar函数。
我的文件名为MyFile.kt。
fun foo() {
    bar()
}

private fun bar() { ... }

如何模拟“bar”函数?
我正在尝试以下方法。
@Test
fun test() {
    mockkStatic("com.mypkg.MyFileKt")

    every { bar() } returns Unit

    foo()

    verify(exactly = 1) { bar() }
}

这会导致编译时错误:无法访问'bar':它在该文件中是私有的

如果我将bar函数变为internal类型,它就可以正常工作。可能我需要对它进行窥探,但找不到相关示例。


1
验证bar()内部发生的事情是一个好主意吗? 我认为应该测试这些而不是方法调用,或者有可能重构一些东西以避免间谍。你认为呢@ashwin?我在思考这个问题,认为根据bar()内部发生的事情,它应该被重构为一个符合SRP的提取类https://anthonysciamanna.com/2016/02/14/should-private-methods-be-tested.html - Robin Vinzenz
1
@RobinVinzenz 你说得没错,我必须进行重构;也许MockK并不支持对顶级私有函数的Spy/Mock。 - Ashwin
1个回答

4
尽管我认为嘲讽私有方法不是一个好主意,因为它们很可能需要与调用它们的方法一起进行测试,但MockK确实支持此操作: https://mockk.io/#private-functions-mocking--dynamic-calls 因此,您的代码应该类似于这样:
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"]() }
}

2
这个会起作用,我只是想知道MockK是否可以模拟/监视Kotlin顶级私有函数。 - Ashwin
据我所知,似乎只能模拟顶层函数,就像你已经做过的那样。 - Erik Finnman
1
这只是胡说八道。更改方法名称会让你整天哭泣。Mockk根本不应该允许这种情况发生,或者应该为这种情况制定一些可靠的API。 - Farid
一定要注意像我一样不要错过 mock["bar"] 后面的 (),否则你会得到一个类型不匹配的错误,需要使用 MockKMatcherScope.DynamicCall。 - Eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接