繁体   English   中英

使用 Mockk 模拟 static java 方法

[英]Mock static java methods using Mockk

我们目前正在使用 java 和 kotlin 项目,慢慢将整个代码迁移到后者。

是否可以使用 Mockk 模拟像Uri.parse()这样的 static 方法?

示例代码会是什么样子?

除了 oleksiyp 回答:

2022 年更新:

你必须使用unmockStatic() 如果自动取消模拟对您不起作用,请阅读另一个答案。

模拟 1.8.1 之后:

Mockk 版本 1.8.1 弃用了以下解决方案。 在该版本之后,您应该执行以下操作:

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

mockkStatic每次调用都会被清除,所以你不再需要 unmock 了


已弃用:

如果您需要模拟行为始终存在,不仅在单个测试用例中,您可以使用@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()
}

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

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") }  
}

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

谨防

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

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

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

除了接受的答案:

你不能像那样创建一个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>()
}

如果我们要模拟静态,例如: mockkStatic(Klass::class)

那么我们肯定要取消模拟它,例如: unmockkStatic(Klass::class)

我建议在 @After 注释的方法中取消模拟它。

一个完整的例子是:

class SomeTest {
  private late var viewMode: SomeViewModel

  @Before
  fun setUp() {
    viewMode = SomeViewModel()
    mockkStatic(OurClassWithStaticMethods::class)       
  }

  @After
  fun tearDown() {
    unmockkStatic(OurClassWithStaticMethods::class)
  }

  @Test
  fun `Check that static method get() in the class OurClassWithStaticMethods was called`() {
    //Given
    every { OurClassWithStaticMethods.get<Any>(any()) } returns "dummyString"

    //When
    viewModel.doSomethingWhereStaticMethodIsCalled()

    //Then
    verify(exactly = 1) { 
       OurClassWithStaticMethods.get<Any>(any()) 
    }
  }
}

本示例使用模拟库“ Mockk ”v.1.12.0 编写

正如上面多个答案中提到的,您必须确保调用 unmockkStatic - 否则您最终会得到不稳定的测试(因为模拟对象/函数将在测试类中可用。

在我的场景中 - 我在 kotlin 中有一个模块范围的扩展 function 并模拟我使用了配套的 object ,如下所示:

class SampleTest {

companion object {
    @BeforeAll
    @JvmStatic
    fun setup() {
        mockkStatic("packagename.filenameKt")
    }

    @AfterAll
    @JvmStatic
    fun teardown() {
        unmockkStatic("packagename.filenameKt")
    }
}}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM