1. 简介

Kotlin 与 Java 高度兼容,这意味着我们可以在 Kotlin 项目中无缝使用大量现成的 Java 库。

本文将介绍如何在 Kotlin 中使用 Mockito 进行 mock 操作。如果你对 Mockito 不太熟悉,可以先阅读我们之前的文章:Mockito 注解详解


2. 环境搭建

首先,创建一个 Maven 项目,并在 pom.xml 中添加 JUnit 和 Mockito 的依赖:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.3.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

别忘了告诉 Maven 项目中使用了 Kotlin,需要配置 Kotlin 插件。具体配置方式可参考 Kotlin 官方文档


3. 在 Kotlin 中使用 Mockito

假设我们有一个类 LendBookManager 需要测试,它依赖一个尚未实现的 BookService 接口:

interface BookService {
    fun inStock(bookId: Int): Boolean
    fun lend(bookId: Int, memberId: Int)
}

LendBookManager 通过构造函数注入了 BookService,并在 checkout 方法中使用了两次:

class LendBookManager(val bookService: BookService) {
    fun checkout(bookId: Int, memberId: Int) {
        if (bookService.inStock(bookId)) {
            bookService.lend(bookId, memberId)
        } else {
            throw IllegalStateException("Book is not available")
        }
    }
}

如果我们不使用 mock,很难对这个方法进行单元测试。Mockito 就派上用场了。

我们可以轻松创建一个 BookService 的 mock 实例,并指定其行为:

val mockBookService = Mockito.mock(BookService::class.java)
Mockito.`when`(mockBookService.inStock(100)).thenReturn(true)

⚠️注意:when 是 Kotlin 的保留关键字,所以调用 Mockito 的 when() 方法时需要用反引号包裹。

接下来,将 mock 实例传入 LendBookManager 并调用测试方法:

val manager = LendBookManager(mockBookService)
manager.checkout(100, 1)
Mockito.verify(mockBookService).lend(100, 1)

还可以测试书籍不在库存时抛出异常的情况:

@Test(expected = IllegalStateException::class)
fun whenBookIsNotAvailable_thenAnExceptionIsThrown() {
    val mockBookService = Mockito.mock(BookService::class.java)
    Mockito.`when`(mockBookService.inStock(100)).thenReturn(false)
    val manager = LendBookManager(mockBookService)
    manager.checkout(100, 1)
}

4. 使用 mockito-kotlin 提升可读性

为了让代码更符合 Kotlin 的风格,可以使用 mockito-kotlin 这个开源库,它对 Mockito 做了 Kotlin 友好的封装:

✅ 示例代码如下:

@Test
fun whenBookIsAvailable_thenLendMethodIsCalled() {
    val mockBookService: BookService = mock()
    whenever(mockBookService.inStock(100)).thenReturn(true)
    val manager = LendBookManager(mockBookService)
    manager.checkout(100, 1)
    verify(mockBookService).lend(100, 1)
}

这个库的优势在于:

  • ✅ 提供 mock() 方法,支持类型推断,无需传参
  • ✅ 使用 whenever() 替代 Mockito 的 when(),无需使用反引号
  • ✅ 语法更简洁、更符合 Kotlin 风格

更多用法可以查看 mockito-kotlin Wiki


5. 小结

本文介绍了如何在 Kotlin 项目中集成 Mockito,并通过 mock 对象进行单元测试。还推荐了一个非常实用的扩展库 mockito-kotlin 来提升代码的可读性和开发效率。

如果你希望查看完整源码,欢迎访问我们的 GitHub 仓库


原始标题:Kotlin with Mockito