alex
alex

Reputation: 970

Mock functional argument of the function

I'm developing web app using Scala, Play Framework. And I need to test controller with the custom action. Please, take a look on the code:

package controllers.helpers

import play.api.mvc.{ActionBuilder, Request, Result}

import scala.concurrent.Future

class CustomAction extends ActionBuilder[Request] {

  override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
    // do some stuff
    block(request)
  }
}


package controllers

import javax.inject.Singleton

import play.api.mvc.Controller

@Singleton
class SomeController @Inject() (customAction: CustomAction
                           ) extends Controller {

  def foo() = customAction(parse.json) { implicit request =>
    // do some stuff and create result
  } 
}

And below you can find a code of the test class. I use Specs2 and I got org.mockito.exceptions.misusing.InvalidUseOfMatchersException on the line with customeActionMock.invokeBlock(any[Request[_]], any[(Request[_]) => Future[Result]]) returns mock[Future[Result]]

package controllers
import controllers.helpers.CustomAction
import org.specs2.mock.Mockito
import play.api.mvc.{Request, Result}
import play.api.test.{FakeHeaders, FakeRequest, PlaySpecification}

import scala.concurrent.Future

class SomeControllerSpec extends PlaySpecification with Mockito {
  private val customeActionMock = mock[CustomAction]
  customeActionMock.invokeBlock(any[Request[_]], any[(Request[_]) => Future[Result]]) returns mock[Future[Result]] //this doesn't work, exception is thrown there


  "SomController" should {
    "respond Ok on valid request" in {
      val result = new UserController(customeActionMock).foo()(FakeRequest())
      status(result) shouldEqual OK
    }
  }
}

I understand that I mock block parameter of the CustomAction incorrectly. Can someone help me to do it properly?

Upvotes: 1

Views: 593

Answers (2)

ecamur
ecamur

Reputation: 99

My project uses Play 2.5.x. I use scalatest. This is how I test controllers.

import org.scalatestplus.play.OneAppPerSuite
import org.scalatest._
import org.scalatest.time.{Millis, Seconds, Span}
import org.scalatest.concurrent.ScalaFutures
import scala.concurrent.Future

class SomeControllerSpec extends FlatSpec with Matchers with ScalaFutures with OneAppPerSuite {
private val customeActionMock = new CustomAction // create an instance of a class 
implicit val defaultPatience = PatienceConfig(timeout =  Span(5,Seconds), interval = Span(500, Millis))

it should "respond Ok on valid request" in {
  val resultF : Future[Result] = new UserController(customeActionMock).foo()(FakeRequest())
  whenReady(resultF) { resultR =>
        resultR.header.status shouldBe 200
    }
  }
}

Upvotes: 1

Thomas Lehoux
Thomas Lehoux

Reputation: 1216

Don't mock the CustomAction :

class SomeControllerSpec extends PlaySpecification with Mockito {
  private val customeActionMock = new CustomAction


  "SomController" should {
    "respond Ok on valid request" in {
      val result = new UserController(customeActionMock).foo()(FakeRequest())
      status(result) shouldEqual OK
    }
  }
}

Upvotes: 0

Related Questions