使用Mockk模拟静态java方法

And*_*icz 12 java static unit-testing kotlin mockk

我们目前正在使用带有kotlin项目的java,慢慢地将整个代码迁移到后者.

是否可以模拟静态方法,如Uri.parse()使用Mockk?

示例代码如何?

Ker*_*ker 21

除了oleksiyp答案:

在模拟1.8.1之后:

Mockk版本1.8.1弃用了以下解决方案.在那个版本之后你应该做:

@Before
fun mockAllUriInteractions() {
    mockkStatic(Uri::class)
    every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")
}
Run Code Online (Sandbox Code Playgroud)

mockkStatic 每次调用时都会被清除,所以你不需要再取消它了


弃用:

如果你需要那个模拟的行为总是在那里,不仅在一个测试用例中,你可以使用@Before和模拟它@After:

@Before
fun mockAllUriInteractions() {
    staticMockk<Uri>().mock()
    every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")    //This line can also be in any @Test case
}

@After
fun unmockAllUriInteractions() {
    staticMockk<Uri>().unmock()
}
Run Code Online (Sandbox Code Playgroud)

这样,如果您希望类的更多部分使用Uri类,您可以在一个地方模拟它,而不是在任何地方污染您的代码.use.

  • 接受的答案写在模拟1.8.1之前,这就是为什么它变得更加准确的原因 (2认同)
  • @LeoColman,当我立即在 `Uri("http", "test", "path")` 上收到编译错误并显示消息“无法创建抽象类的实例”和“参数过多”时,您的解决方案应该如何工作public/*package*/ 构造函数 Uri() 在 android.net.Uri 中定义”?我使用的是模拟1.10.0 (2认同)
  • 我不明白这个答案怎么会得到 73 票赞成,而使用 Uri() 构造函数(A)是私有的,B)该类是抽象的...... (2认同)

小智 12

MockK允许模拟静态Java方法.它的主要目的是模拟Kotlin扩展函数,因此它没有PowerMock那么强大,但它仍然可以用于Java静态方法.

语法如下:

staticMockk<Uri>().use {
    every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")

    assertEquals(Uri("http", "test", "path"), Uri.parse("http://test/path"))

    verify { Uri.parse("http://test/path") }  
}
Run Code Online (Sandbox Code Playgroud)

更多细节:http://mockk.io/#extension-functions

  • 注意:staticMockk 已弃用并替换为:“mockkStatic(T::class)” (5认同)

Dan*_*mes 6

除了已接受的答案:

你不能创建Uri这样的,你还必须模拟 Uri 实例。就像是:

private val mockUri = mockk<Uri>()

@Before
fun mockAllUriInteractions() {
    mockkStatic(Uri::class)
    every { Uri.parse("http://test/path") } returns mockUri
    // or just every { Uri.parse("http://test/path") } returns mockk<Uri>()
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*sky 6

谨防

如果mockkSatic()不带块调用,请不要忘记在调用unmockkStatic()模拟方法后调用。该方法不会自动取消模拟,即使在不调用mockkStatic()而是使用静态方法的不同测试类中,您仍然会获得模拟值。

另一种选择是在块内执行模拟方法,然后它将自动取消模拟:

mockkStatic(Uri::class) {
    every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")
    val uri = Uri.parse("http://test/path")
}

Run Code Online (Sandbox Code Playgroud)