使用 Mockk 模拟静态 java 方法
Mock static java methods using Mockk
我们目前正在 java 与 kotlin 项目合作,慢慢将整个代码迁移到后者。
是否可以使用 Mockk 模拟 Uri.parse()
等静态方法?
示例代码会是什么样子?
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
除了 oleksiyp 回答:
mockk 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()
}
这样,如果您希望 class 的更多部分使用 Uri class,您可以在一个地方模拟它,而不是用 .use
污染您的代码无处不在。
除已接受的答案外:
您不能像那样创建 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>()
}
当心
如果您调用 mockkSatic()
时没有阻塞,请不要忘记在调用模拟方法后调用 unmockkStatic()
。该方法不会自动取消模拟,即使在不调用 mockkStatic()
但使用静态方法的不同测试 类 中,您仍然会获得模拟值。
另一种选择是在块内执行模拟方法,然后它会自动取消模拟:
mockkStatic(Uri::class) {
every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")
val uri = Uri.parse("http://test/path")
}
如果我们要模拟静态,比如: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
编写的
我们目前正在 java 与 kotlin 项目合作,慢慢将整个代码迁移到后者。
是否可以使用 Mockk 模拟 Uri.parse()
等静态方法?
示例代码会是什么样子?
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
除了 oleksiyp 回答:
mockk 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()
}
这样,如果您希望 class 的更多部分使用 Uri class,您可以在一个地方模拟它,而不是用 .use
污染您的代码无处不在。
除已接受的答案外:
您不能像那样创建 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>()
}
当心
如果您调用 mockkSatic()
时没有阻塞,请不要忘记在调用模拟方法后调用 unmockkStatic()
。该方法不会自动取消模拟,即使在不调用 mockkStatic()
但使用静态方法的不同测试 类 中,您仍然会获得模拟值。
另一种选择是在块内执行模拟方法,然后它会自动取消模拟:
mockkStatic(Uri::class) {
every { Uri.parse("http://test/path") } returns Uri("http", "test", "path")
val uri = Uri.parse("http://test/path")
}
如果我们要模拟静态,比如: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
编写的