0
votes

I have created a Workflow Processor Trait similar to the one mentioned below:

import org.scalatestplus.play._
import play.api.mvc._
import play.api.test._
import play.api.test.Helpers._
import org.scalatest.Matchers._
import org.scalamock.scalatest.MockFactory
import utils.OAuthUtils._
import utils.OAuthUtils
import utils.OAuthProcess
import play.api.Application
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import play.api.libs.json.JsResult
import play.api.libs.json.Json
import play.api.libs.json.JsSuccess
import play.api.libs.json.JsError
import play.api.libs.ws.WS



trait MyProcess[A] {
  type B
  type C
  type D
  def stage1(s: String): B
  def stage2(b: B)(implicit e: ExecutionContext, app: Application, a: A):       Future[C]
  def stage3(c: C)(implicit e: ExecutionContext, app: Application, a: A): Future[JsResult[D]]
  def process(s: String)(implicit e: ExecutionContext, app: Application, a: A): Future[JsResult[D]] = {
   val b = stage1(s)
   val f_d = for {
      c <- stage2(b)
      d <- stage3(c)
   } yield d
   f_d
 }
}

Now I would like to Unit test this code. So I created a nicer little scalatest scalamock test suite:

class TestController extends PlaySpec with Results with MockFactory {
  "MyController" must {
    " testing for method process" in {
  running(FakeApplication()) {

    implicit val context = scala.concurrent.ExecutionContext.Implicits.global
    implicit val s = "implicit String"
    implicit val currentApp = play.api.Play.current

  case class TestParms(s: String)
  abstract class TestProcessor extends MyProcess[TestParms] {
      type B = String
      type C = String
      type D = String
    }

    implicit val t = stub[TestProcessor]
    t.stage1(_: String).when(token).returns(testToken)

    (t.stage2(_: String)(_: ExecutionContext, _: Application, _: TestParms)).when(token, context, currentApp, tp).returns({
      Future.successful(stage2String)
    })
    (t.stage3(_: String)(_: ExecutionContext, _: Application, _: TestParms)).when(token, context, currentApp, tp).returns({
      Future.successful(Json.fromJson[String](Json.parse(stage3String)))
     })
   }
 }
}
}

My expectation is to set this stub on a different class and test the class. Stubs (t.stage2 and t.stage3) compile fine but the following statement doesn't compile.

 t.stage1(_: String).when(token).returns(testToken)

Compiler reports the following issue:

overloaded method value when with alternatives:   (resultOfAfterWordApplication: org.scalatest.words.ResultOfAfterWordApplication)Unit <and>   (f: => Unit)Unit  cannot be applied to (String)  TestController.scala  /play-scala/test/controllers

Could someone help? I am finding it very difficult to write Unit tests for Scala classes as well as mocking them.

Scalatest versions from Build.sbt:

 "org.scalatestplus" %% "play" % "1.2.0" % "test",
 "org.scalamock" %% "scalamock-scalatest-support" % "3.2" % "test",
1
I have tested this outside play spec and was able to get it to compile. I am not sure as t whats happening with the statement being inside the PlaySpec.user3916622

1 Answers

0
votes

Try wrapping the invocation in parens

(t.stage1(_: String)).when(token).returns(testToken)

I believe scalac thinks you're trying to call when on an instance of String (since that would be what's returned by t.stage1(_)).