是否可以在不打开 class 的情况下将 Mockito 与 Kotlin 一起使用?

Is it possible to use Mockito with Kotlin without open the class?

我们可能知道,默认情况下 Kotlin class 一旦定义,它就是最终的,除非明确声明 open

当我们想使用 Mockito 模拟它时,这将是 post 一个挑战。我们需要将其显式声明为 open。有没有一种方法可以避免将其声明为 open,同时能够为我们的测试模拟它?

我知道可以通过三种方式模拟 Kotlin classes:

  1. 使用接口而不是 classes。在这种情况下,您将特定 class 的所有用法替换为相应的接口。在测试代​​码中,您模拟了界面。

    interface Something { /* ... */ }
    
    class SomethingImpl : Something { /* ... */ }
    
    fun processSomething(something: Something) { /* ... */ }
    
    val something = mock(Something::class.java)
    processSomething(mock)
    
  2. 让class打开,不太方便

  3. 使用 PowerMock 而不是 Mockito。使用它的 ClassLoader 你可以做的比 Mockito 多得多。

我更喜欢第一种方法,因为使用接口而不是 classes 是个好主意,即使您不使用模拟框架也是如此。

Mockito2 现在也可以模拟最终 类。

但是,此功能是选择加入,因此您需要手动启用它。
为此,您需要定义一个包含行 mock-maker-inline

的文件 /mockito-extensions/org.mockito.plugins.MockMaker

参见示例
http://hadihariri.com/2016/10/04/Mocking-Kotlin-With-Mockito/https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable
快速介绍

旁注,目前 doesn't work for android

运行 espresso 测试时,MockMaker 插件似乎不起作用。因此,您可以改用 Kotlin 的 all-open pugin

在build.gradle中添加插件:

buildscript {
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
    }
}

apply plugin: "kotlin-allopen"

指定将使 class 打开的注释:

allOpen {
    annotation("com.my.MyMockable")
}

创建可用于注释 classes:

的注释
@Target(AnnotationTarget.CLASS)
annotation class MyMockable

然后,为了使您的 class 及其 public 方法可模拟(打开),用您的注释对其进行注释:

@MyMockable