【问题标题】:Kotlin/Mockito: How to mock "annotationClass" from kotlin.AnnotationKotlin/Mockito:如何从 kotlin.Annotation 模拟“annotationClass”
【发布时间】:2020-12-04 23:57:02
【问题描述】:

我想模拟注释以检查根据给定注释返回结果的类的良好行为。

这是我使用 OneToOne 注释检查良好行为的测试之一:

@Test
fun <T> supports_when_field_has_OneToOne_annotation_with_eager_fetch_type() {
    val myHandler = MyHandler<T>()

    val joinAnnotation = mock<OneToOne> {
        on { this.fetch }.thenReturn(FetchType.EAGER)
        onGeneric { this.annotationClass }.thenReturn(OneToOne::class)
    }
    val supports = myHandler.supports(joinAnnotation)

    assertThat(supports).isTrue()
}

当我运行测试时,出现以下错误:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: annotationType() 不能返回 KClassImpl annotationType() 应该返回 Class


如果您不确定为什么会出现上述错误,请继续阅读。 由于上述语法的性质,可能会出现上述问题,因为:

  1. 此异常可能发生在错误编写的多线程测试中。 有关并发测试的限制,请参阅 Mockito 常见问题解答。
  2. 使用 when(spy.foo()).then() 语法对间谍进行存根。存根间谍更安全-
    • 使用 doReturn|Throw() 系列方法。更多关于 Mockito.spy() 方法的 javadocs。

mockito调用以下代码时出现此错误:

onGeneric { this.annotationClass }.thenReturn(OneToOne::class)

如果我删除这一行,我就可以模拟 Annotation。 (模拟 'fetch' 属性效果很好),但我的测试没有通过,因为我需要模拟 'annotationClass'

我不明白为什么我有错误,为什么错误与annotationType()(java注释方法)有关?

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: java kotlin annotations mockito mockito-kotlin


    【解决方案1】:

    我找到了解决问题的方法。

    kotlin.Annotation.annotationClass是kotlin扩展函数:

    /**
     * Returns a [KClass] instance corresponding to the annotation type of this annotation.
     */
    public val <T : Annotation> T.annotationClass: KClass<out T>
        get() = (this as java.lang.annotation.Annotation).annotationType().kotlin as KClass<out T>
    

    这个函数调用java.lang.annotation.Annotation.annotationType()

    我无法模拟扩展函数,因为 kotlin 将扩展函数转换为静态方法,而 Mockito 无法存根静态方法。

    所以我直接嘲讽java.lang.annotation.Annotation.annotationType()

    这是我的新代码:

    @Test
    fun <T> supports_when_field_has_OneToOne_annotation_with_eager_fetch_type() {
        val myHandler = MyHandler<T>()
    
        val joinAnnotation = mock<OneToOne> {
            on { this.fetch }.thenReturn(FetchType.EAGER)
            on { (this as java.lang.annotation.Annotation).annotationType() }.thenReturn(OneToOne::class.java)
        }
        val supports = myHandler.supports(joinAnnotation)
    
        assertThat(supports).isTrue()
    }
    

    有模拟静态方法的替代方法(PowerMock、MockK),但我没有测试。

    如果有人有更好的建议,我很想看看。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多