【问题标题】:Mocking generic interfaces with Kotlin and Mockito使用 Kotlin 和 Mockito 模拟通用接口
【发布时间】:2016-11-08 20:15:24
【问题描述】:

我正在尝试使用 Mockito 在 Kotlin 中模拟一个通用接口。但到目前为止,我还没有找到自然的解决方案。给定:

interface X<T> {
    fun x(): T
}

fun f(x: X<Int>) = x.x()

我可以用以下任何一种来模拟X

  1. val x = f(Mockito.mock(X::class.java) as X&lt;Int&gt;)

    但这会产生“未经检查的演员表”警告。

  2. @Mock lateinit var x: X&lt;Int&gt;

    但我不想使用 @Mock 注释,因为我希望我的字段是最终的。

  3. 引入一个辅助函数,就像 mockito-kotlin library 所做的那样:

    inline fun &lt;reified T : Any&gt; mock(): T = Mockito.mock(T::class.java)!!

    然后这样称呼它:

    val x: X&lt;Int&gt; = mock()

    但我不想使用辅助函数。

是否有一种优雅的纯 Kotlin 方式来模拟使用 Mockito 的通用接口? (我更喜欢没有警告的 1. 版本。)

【问题讨论】:

  • 为什么不想使用辅助函数? val x = f(mock&lt;X&lt;Int&gt;&gt;()) 有什么问题?
  • 因为它感觉像是解决“未经检查的演员表”问题的一种解决方法。有没有办法在没有解决方法的情况下做到这一点?
  • 我不认为 reified type parameters 可以解决“未经检查的演员表”问题。事实上,我将“未经检查的强制转换”问题视为(Java)解决方法,以解决没有具体类型参数(或类似的东西)。
  • @mfulton26 想了想,我完全同意你的看法!

标签: mocking mockito kotlin


【解决方案1】:

只需使用mockito-kotlin 项目。这个项目包含所有必须有 mockito 的助手。并且还支持 mockito 2.1。

更新。要处理“未经处理的演员表”,请使用Reified type parameters

你说“但是我不想使用辅助函数。”但是为什么呢?这是内联函数,因此在编译时函数将在所有调用站点内联。

【讨论】:

  • 我确实使用了那个库,但这不是这里的问题。我确实想知道是否有办法以更直接的方式绕过“未经检查的演员表”警告。
  • 我想我明白了。这不是 Kotlin 的问题,而是 Java 编写的 Mockito 接口的问题,无法表达这一点。如果 Mockito 使用具体的类型参数,一切都会好起来的。
【解决方案2】:

您也可以使用Mockk 库。

它支持注解,所以要创建一个mock就足够了:

@ExtendWith(MockKExtension::class)
class BookSpec {

  @MockK
  lateinit var author: Author
}

然后记录一些行为:

every { author.name() } returns "Milosz Brzezinski"

every { author.rank() } throws OutOfScaleException()

【讨论】:

    【解决方案3】:

    mockito-kotlin 库确实可以防止在正确使用时抑制警告的需要。

    这是一个例子。在 Maven pom.xml 中导入库:

    <dependency>
        <groupId>com.nhaarman.mockitokotlin2</groupId>
        <artifactId>mockito-kotlin</artifactId>
        <version>2.2.0</version>
    </dependency>
    

    然后在您的测试中,您导入模拟方法:

    import com.nhaarman.mockitokotlin2.moc
    

    然后你可以轻松地模拟任何你需要模拟的东西:

    @Before
    fun setUp() {
        val sessionFactory: FactoryBean<SessionFactory> = mock()
        val eventDateReminderService: EventDateReminderService = mock()
        val eventDateService: EventDateService = mock()
        val templateService: TemplateService = mock()
        reminderService = ReminderService(sessionFactory, eventDateReminderService, eventDateService, templateService)
    }
    

    无需强制转换或抑制警告。如果您直接使用 Mockito 库,则需要强制转换和禁止警告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      • 2019-04-17
      • 2022-06-10
      相关资源
      最近更新 更多