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",