Mockk:如何模拟对象保存时生成的对象 ID(答案 + vararg)

Mockk: How to mock object id being generated when object is saved (answers + vararg)

在我的测试中,我需要模拟一种情况,当使用实体管理器 (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<MyObj>().

时会发生异常

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

正如 Михаил Нафталь 在他的评论中指出的那样,如果模拟方法使用可变参数,则参数将作为第一个参数中的数组传递给 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 部分有更优雅的处理可变参数的方法,但我无法在文档中找到任何方法。欢迎改进提示:)