Search code examples
scalaunit-testingscalamock

How to mock a call by name function using ScalaMock?


I'd like to be able to mock my call-by-name function with ScalaMock, so it can run the passed function inside my mock.

class MyTest extends Specification with MockFactory {

  trait myTrait {
    def myFunction[T](id: Int, name: String)(f: => T): Either[ErrorCode,T]
  }

  def futureFunction() = Future {
    sleep(Random.nextInt(500))
    10
  }

  "Mock my trait" should {
    "work" in {
      val test = mock[myTrait]

      (test.myFunction (_: Int)(_: String)(_: T)).expects(25, "test",*).onCall {
        _.productElement(2).asInstanceOf[() => Either[ErrorCode,T]]()
      }
      test.myFunction(25)("test")(futureFunction()) must beEqualTo(10)
    }
  }

}

I tried mock the function this way:

(test.myFunction (_: Int)(_: String)(_: T)).expects(25, "test",*).onCall {
    _.productElement(2).asInstanceOf[() => Either[ErrorCode,T]]()
  }

but when I run the test, I get this error:

scala.concurrent.impl.Promise$DefaultPromise@69b28a51 cannot be cast to  Either

How can I mock it , so it runs my futureFunction() inside mock and return the result.


Solution

  • A friend helped me to find the solution. The problem is related with my mock for myFunction(). I pass a call-by-name function to myFunction()(f: => T) which returns T, after evaluating it, myFunction() returns Either[ErrorCode, T]. So the mock should be like that:

    (test.myFunction (_: Int)(_: String)(_: T)).expects(25, "test",*).onCall { test =>
        Right(test.productElement(2).asInstanceOf[() => T]())
    }