Mockito → MockK
老写法(Java + Mockito)
java
@Mock ApiService apiService;
@Captor ArgumentCaptor<String> captor;
@Test
public void test() {
when(apiService.loadItems()).thenReturn(items);
verify(apiService, times(1)).loadItems();
}
问题在哪里
Mockito 对 Kotlin 的支持不够好------final 类和 final 方法在 Kotlin 中默认不可 mock,需要额外配置。不支持 suspend 函数(除非用 mockito-kotlin 桥接库)。语法是 Java 风格的 when(...) 而非 Kotlin 惯用的 DSL。
新写法(MockK)
kotlin
// 基础用法 --- 和 Mockito 相似但更 Kotlin 化
@MockK lateinit var apiService: ApiService
@Test
fun test() = runTest {
every { apiService.loadItems() } returns items
viewModel.loadItems()
verify(exactly = 1) { apiService.loadItems() }
}
// suspend 函数 --- MockK 原生支持
coEvery { apiService.loadItems() } returns items
coVerify { apiService.loadItems() }
// Slot --- 替代 ArgumentCaptor
val slot = slot<String>()
every { apiService.search(capture(slot)) } returns items
viewModel.search("query")
assertEquals("query", slot.captured)
// relaxed mock --- 所有方法自动返回默认值
@RelaxedMockK lateinit var repo: ItemRepository
一句话注意
MockK 是 Kotlin 原生的 mocking 库,every {} 替代 when(),verify {} 替代 verify(),coEvery/coVerify 处理 suspend 函数。最重要的是 MockK 不需要 mock-maker-inline 配置就能 mock final 类,Kotlin 的默认行为就是 final。
Mockito 的 argThat(argumentMatcher) 在 MockK 里用 lambda:match<Item> { it.id == 1 },比 Java 的 ArgumentMatcher 简洁很多。
Java Android 老项目迁移系列,持续更新中。