在scala play 2.4中以函数作为参数调用doAnswer

Posted

技术标签:

【中文标题】在scala play 2.4中以函数作为参数调用doAnswer【英文标题】:Call doAnswer with function as argument in scala play 2.4 【发布时间】:2015-11-20 15:34:28 【问题描述】:

我想模拟一个在参数中接受回调的方法,比如说:

methodToMock[T](callback: (String, String) => T)

使用 play 2.3,(specs2 版本 2.3.8)我设法使用来自 mockito 的方法 doAnswer 做到了:

doAnswer( invocation =>
  val method = invocation.asInstanceOf[(String, String) => Any] // L.34
  method(role, key)
).when(myMock).methodToMock[Any](any)

但是由于play 2.4(使用特殊依赖specs2,版本2.4.2),之前的代码行不通,告诉我:

[Ljava.lang.Object; cannot be cast to scala.Function2 (MySpec.scala:34)

我真的不明白为什么 mockito 开始在我的代码中使用 Java 对象,因为我使用的是 specs2 implementation 并且没有找到任何关于 doAnswer 修改的文档,也没有找到我的用例的使用示例。

你知道我做错了什么以及解决这个问题的方法吗?

编辑

我想展示一个简化的案例,但那删除了问题的根源......方法的真正定义还需要一个隐式参数列表:

methodToMock[T](callback: (String, String) => T)(implicit value: String)

这意味着 specs2 似乎返回一个数组而不是单个元素(虽然它的行为在两个版本之间确实发生了变化)。

下面的代码现在可以工作了

doAnswer( invocation =>
  val firstArgList = invocation.asInstanceOf[Array[Object]](0)
  val method = firstArgList.asInstanceOf[(String, String) => Any] // L.34
  method(role, key)
).when(myMock).methodToMock[Any](any)(any)

【问题讨论】:

[Ljava.lang.Object; 表示您正在访问一个值数组而不是第一个参数。 你是对的!我专注于演员阵容,并没有考虑到我在第一个之后有一个隐含的参数列表,我会更新我的问题。 【参考方案1】:

您使用的是哪个版本的 specs2?使用3.6.5(最新),以下工作正常

case class T() 
  def methodToMock[A](callback: (String, String) => A) = 1


val m = mock[T]

doAnswer( invocation =>
  val method = invocation.asInstanceOf[(String, String) => Any] // L.34
  method("role", "key")
).when(m).methodToMock[Any](any)

m.methodToMock((s: Any, s2: Any) => s.toString.size + s2.toString.size) === 7

【讨论】:

以上是关于在scala play 2.4中以函数作为参数调用doAnswer的主要内容,如果未能解决你的问题,请参考以下文章

在 Play 2.4 scala 中禁用单个测试

在 Play Framework 2.4 中为 Scala 实现 Akka

在 Play Framework 2.4 中为 Scala 实现 CORS

如何在 play framework(scala) 2.4 中获取当前会话或请求对象?

在 Scala Play 框架 2.4 中使用两个资产目录

如何在 play 2.4 中的 scala 模板中设置类型列表字段的值?