【问题标题】:Open getter in Kotlin to use it with Mockito - MissingMethodInvocationException在 Kotlin 中打开 getter 以将其与 Mockito 一起使用 - MissingMethodInvocationException
【发布时间】:2018-09-06 23:14:34
【问题描述】:

Kotlin 可以自动为主要的构造函数参数创建 getter(这很棒),并且所有这些 getter 默认情况下都是最终的(未打开)。 我有一门课(在 Kotlin 中):

open class SongCategory(val id: Long,
                        val type: SongCategoryType,
                        val name: String? = null,
                        var displayName: String? = null,
                        var songs: List<Song>? = null) {
}

我想在一些 Mockito 测试(Java 中)中使用它:

SongCategory songCategory = mock(SongCategory.class);
// the line below produces MissingMethodInvocationException
when(songCategory.getDisplayName()).thenReturn("Dupa");

这会产生 MissingMethodInvocationException,因为 Mockito 需要打开模拟类(不是最终的),而模拟方法 getDisplayName() 必须打开,但事实并非如此。

我无法打开此 getter 或创建另一个覆盖 getter,因为它与为构造函数自动创建的最终 getter 冲突。

我可以将这些所有参数移动到辅助构造函数并分别创建所有属性和 getter。但是,如果我必须编写与 Java 相同的样板代码,那么使用 Kotlin 有什么意义呢?

有没有办法将 Mockito 与 Kotlin 编译的 getter 一起使用?

【问题讨论】:

    标签: java kotlin mockito getter


    【解决方案1】:

    不要为了测试而open你的班级。而是尝试使用编译器插件为您执行此操作。你可以在这里阅读:https://kotlinlang.org/docs/reference/compiler-plugins.html#all-open-compiler-plugin

    完成后,您将能够像使用任何其他 Java 类一样使用 Mockito。

    【讨论】:

    • 它正在工作!但是这个编译器插件需要用一些特殊的注释对类进行注释,所以仍然只是为了测试而打开类(现在我在类旁边有'@Open'注释而不是'open'关键字)。跨度>
    【解决方案2】:

    其实我发现打开getter的语法很简单(虽然官方文档里没有):

    open class SongCategory(...
                            open var displayName: String? = null,
                            ...) {
    }
    

    这会打开一个属性的 getter 和 setter。

    【讨论】:

      【解决方案3】:

      你可以尝试使用PowerMock处理final方法

      或者Javasist及其javassist.Modifier

      【讨论】:

        【解决方案4】:

        我同意@Unknown 的观点,有些地方可以使用kotlin-allopen 插件。但在这种情况下,由于您要做的只是模拟一个 Kotlin 类(未打开),因此您只需添加 mockito-inline 插件。

        将以下内容添加到您的build.gradle:

        testImplementation 'org.mockito:mockito-core:2.13.0' // use the latest version
        testImplementation 'org.mockito:mockito-inline:2.13.0'
        

        【讨论】:

        • 您的解决方案似乎是最好的解决方案,但在添加 mockito-inline 依赖项后,我收到错误“Android 不支持此模拟制造商”。这很奇怪,因为它在 JDK 单元测试上运行,而不是在 Android 上。很可能,问题在于依赖项冲突。
        • 您在项目中使用 Roboelectric 吗?
        • 我确实使用了 Roboelectric,但即使我扔掉了 Roboelectric、Kotlin 和所有库,问题仍然存在。即使在一个空项目上,这个库 'org.mockito:mockito-inline:2.13.0' 似乎也与我的 JDK(Open JDK 1.8.0_152)冲突。
        猜你喜欢
        • 2016-07-31
        • 2019-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多