【问题标题】:How to do non specialized type has method that accepts Function1?如何做非专业类型有接受 Function1 的方法?
【发布时间】:2018-06-03 14:07:12
【问题描述】:

我有以下课程:

class Elem[T](t: T){
  def doSome(f: T => Unit):Unit = f(t)
}

所以我想测试给定Elem 实例的函数调用(我正在使用mockito)。运行测试时

val f = mock(classOf[Int => Unit])
new Elem(1).doSome(f)
verify(f).apply(1)

我遇到了以下异常:

Wanted but not invoked:
function1.apply$mcVI$sp(1);

However, there was exactly 1 interaction with this mock:
function1.apply(1);

这是合理的,因为 Function1 专门用于 Int。所以将测试设为

val f = mock(classOf[AnyRef => Unit])
new Elem(1.asInstanceOf[AnyRef]).doSome(f)
verify(f).apply(1.asInstanceOf[AnyRef])

工作正常。

有没有办法避免这种丑陋的演员表AnyRef?也许还有比 mockito 更适合这种情况的工具?

【问题讨论】:

  • 在最后一个代码sn-p中,两个asInstanceOf真的有必要吗,或者如果你做new Elem(1)并且只保留最后一个asInstanceOf就足够了吗?
  • @AndreyTyukin 不幸的是,是的。删除这些强制转换会使测试无法编译。

标签: scala function testing mockito


【解决方案1】:

这是强制编译器使用非专用泛型apply 的一种方法:

  def verifyGenericApply[X, Y](f: X => Y, x: X): Unit = {
    verify(f).apply(x)
  }

  "Int function" should "invoke non-specialized apply" in {
    class Elem[T](t: T){
      def doSome(f: T => Unit):Unit = f(t)
    }
    val f = mock(classOf[Int => Unit])
    new Elem(1).doSome(f)
    verifyGenericApply(f, 1)
  }

我对 mockito 不够熟悉,无法保证这是惯用的,不过...

【讨论】:

  • 看起来很可爱。谢谢。
【解决方案2】:

ScalaMock 似乎开箱即用:

import org.scalatest._
import org.scalatest.matchers._
import org.scalamock.scalatest.MockFactory
import org.scalamock.scalatest._

class Elem[T](t: T){
  def doSome(f: T => Unit):Unit = f(t)
}

class ExampleSpec extends FlatSpec with Matchers with MockFactory {

  "Elem.doSome" should "apply given function once" in {
    val f = mockFunction[Int, Unit]
    f.expects(1).returning({}).once
    new Elem(1).doSome(f)
  }
}

run(new ExampleSpec)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    相关资源
    最近更新 更多