【问题标题】:Mockk: How to mock object id being generated when object is saved (answers + vararg)Mockk:如何在保存对象时模拟生成的对象 ID(答案 + vararg)
【发布时间】:2020-10-06 13:19:29
【问题描述】:

在我的测试中,我需要模拟一种情况,当使用实体管理器 (em) 将新对象保存到数据库中并且在此过程中,该对象的 id 属性设置为该行的自动递增 id在数据库中。我想将 id 属性设置为我自己的值,以便稍后在测试中匹配。

我正在使用 mockk 1.9.3 和 kotlin 1.4.0。

到目前为止,我有这个:

val myVal = 123

every { 
     em.persist(any<MyObj>()) 
} answers {
     firstArg<MyObj>().id = myVal
     // return of the persist method
     em
}

编辑:em.persist 方法看起来像这样,问题可能与第一个参数是可变参数有关。

open fun persist(vararg o: Any?): T {
    o.forEach { doThePersist(it) }
    return this as T
}

但是当我尝试运行该代码时,我得到:

java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class MyObj

看起来问题出在firstArg 电话中。如果我在该行放置一个断点,它将到达它并停在那里,当我尝试评估 firstArg&lt;MyObj&gt;() 时会发生异常。

在文档中,我只能找到使用简单 Int 的示例或有关如何匹配可变参数的示例。有什么想法为什么会抛出ClassCastException 或如何在answers 部分正确处理可变参数?

【问题讨论】:

  • vararg 基本上是一个带有一些魔法的数组。它可以与(firstArg&lt;Array&lt;Object&gt;()[0] as MyObj).id = myValfirstArg&lt;Array&lt;MyObj&gt;()[0].id = myVal 一起使用吗?
  • 你是对的,lambda 的第一个参数中有一个数组,这就是为什么我无法转换第一个参数并获得 ClassCastException。测试了,它可以工作,谢谢:)

标签: kotlin testing mockk


【解决方案1】:

正如 Михаил Нафталь 在他的评论中指出的那样,如果模拟方法使用可变参数,则参数将作为第一个参数中的数组传递给 answers lambda。此解决方案适用于我的情况:

val myVal = 123

every { 
     em.persist(any<MyObj>()) 
} answers {
     val myObj = firstArg<Array<*>>()[0].id as MyObj
     myObj.id = myVal
     // return of the persist method
     em
}

我不必在every 部分对可变参数使用特殊匹配器,因为我只需要匹配我的案例中的第一个参数。

也许在answers 部分有更优雅的处理可变参数的方式,但我在文档中找不到任何内容。欢迎改进提示:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-15
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 2018-07-31
    • 1970-01-01
    相关资源
    最近更新 更多