【问题标题】:Is it possible to use Mockito with Kotlin without open the class?是否可以在不打开课程的情况下将 Mockito 与 Kotlin 一起使用?
【发布时间】:2016-07-31 21:48:36
【问题描述】:

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

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

【问题讨论】:

标签: unit-testing mocking mockito kotlin


【解决方案1】:

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

在 build.gradle 中添加插件:

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

apply plugin: "kotlin-allopen"

指定将使类打开的注释:

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

创建可用于注释类的注释:

@Target(AnnotationTarget.CLASS)
annotation class MyMockable

然后,为了使您的类及其公共方法可模拟(打开),请使用您的注解对其进行注解:

@MyMockable

【讨论】:

  • 我喜欢这种解决方案,因为它干扰性最小,并且可以最大程度地控制替代方案。
【解决方案2】:

Mockito2 现在也可以模拟 final 类。

但是,此功能是选择加入,因此您需要手动启用它。
为此,您需要定义一个文件/mockito-extensions/org.mockito.plugins.MockMaker,其中包含mock-maker-inline

参见例如
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

【讨论】:

  • 它是否与 dexmaker 一起使用?对于 Android Instrumentation 测试?
  • @folkyatina 不知道,抱歉
  • 这对我也不起作用,而且显然不支持 Android:github.com/mockito/mockito/pull/648
  • @amitav13 是的,不幸的是。但是,该问题未标记为android。但我会更新答案以使这一点更清楚
  • 对于 Android Instrumentation 测试,我们可以使用 dexopener,它会打开最终类,而无需修改它们或添加注释。
【解决方案3】:

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

  1. 使用接口而不是类。在这种情况下,您用相应的接口替换特定类的所有用法。而在测试代码时,你会模拟接口。

    interface Something { /* ... */ }
    
    class SomethingImpl : Something { /* ... */ }
    
    fun processSomething(something: Something) { /* ... */ }
    
    val something = mock(Something::class.java)
    processSomething(mock)
    
  2. 开课,不是很方便。

  3. 使用 PowerMock 代替 Mockito。使用它的ClassLoader,你可以做的比使用 Mockito 多得多。

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

【讨论】:

  • 谢谢迈克尔。那么对于我们需要测试的每个类,我们都需要实现一个接口吗?这听起来比“打开”课程更多的代码更改,或者我错过了什么......
  • 当然,但这是朝着更好的架构迈出的一大步:)
  • 在没有正当理由的情况下(从 OO 或 API 设计的角度)创建一个单独的接口是过度工程化的,因为它只会增加复杂性。这比不必要地上课open 还要糟糕。 (而且,不,不创建接口违反了 GoF 的“程序到接口,而不是实现”的原则。)
  • 这个问题太笼统了,没有一个正确的答案,但在我看来,需要模拟的类通常作为依赖项注入,并在其中注入其他依赖项。在这种情况下,为此类类创建单独的接口是一个好主意,因为它有助于使系统松散耦合和单元测试更容易甚至可能。这对我来说是一个非常正当的理由。
  • 这有点跑题了,但想指出使用接口并不一定会减少耦合。你总是依赖合同。如果只是将所有公共方法移动到一个接口中,则不会影响耦合,只是增加了代码行。一个类有一个接口 + 实现,但是当你传递一个对象时,它只是一切都依赖的接口(契约)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
相关资源
最近更新 更多