Some Name
Some Name

Reputation: 9540

How to do non specialized type has method that accepts Function1?

I have the following class:

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

So I want to test function invokation for the given Elem instance (I'm doing with mockito). When running the test

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

I got the following exception:

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

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

That's reasonable because Function1 is specialized for Int. So making the test as

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

works fine.

Is there a way to avoid this ugly casts to AnyRef? Maybe there is another tool more suitable for this case than mockito?

Upvotes: 2

Views: 46

Answers (2)

Mario Galic
Mario Galic

Reputation: 48420

ScalaMock seems to work out-of-the-box:

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)

Upvotes: 2

Andrey Tyukin
Andrey Tyukin

Reputation: 44928

Here is one way to force the compiler to use the non-specialized generic 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)
  }

I'm not familiar enough with mockito to guarantee that this is idiomatic, though...

Upvotes: 4

Related Questions