Testing controller which uses Action made by me play framework

Viewed 24

I created an Action:

    class AuthAction @Inject() (
    bodyParser: BodyParsers.Default,
    authService: AuthService,
    dao: InvoicerDao
)(implicit ec: ExecutionContext)
    extends ActionBuilder[UserRequest, AnyContent] {
  override def parser: BodyParser[AnyContent] = bodyParser

  override protected def executionContext: ExecutionContext = ec

  private val headerTokenRegex: Regex = """(.+?)""".r

  override def invokeBlock[A](
      request: Request[A],
      block: UserRequest[A] => Future[Result]
  ): Future[Result] =
    extractBearerToken(request)
      .map { token =>
        authService.validateJwt(token) match {
          case Success(session) =>
            searchForUser(request, block, session)
          case Failure(t) =>
            Future.successful(
              Results.Unauthorized(t.getMessage)
            )
        }
      }
      .getOrElse {
        Future.successful(Results.Unauthorized)
      }

I'm using this in my controller:

class InvoiceController @Inject() (
    cc: ControllerComponents,
    authAction: AuthAction,
    dao: InvoicerDao
) extends AbstractController(cc) {

  val logger: Logger.ALogger = Logger.of(classOf[LoginController])

  import models.JsonFormats._

  def saveInvoice: Action[AnyContent] = authAction { implicit userRequest =>
    userRequest.request.body.asJson
      .map(jsValue =>
        jsValue
          .validate[InvoiceWithParts]
          .map(invoice => {
            dao.saveInvoice(invoice.invoice.copy(date = DateTime.now()), invoice.parts)
            Ok("Invoice saved!")
          })
          .getOrElse(BadRequest("The invoice can't be parsed to json!"))
      )
      .getOrElse(BadRequest("The body can't be parsed to json!"))
  }

I want to test this saveInvoice method somehow mocking out the authAction. I tried: play docs and all the stack overflow pages I could find.

Please help me test this.

Test looks like this: I know that it is not correct like this because it throws nullpointer exception. When I tried the play documentation way (with materializer and Helpers.call) it didn't work, my authAction was called instead of the "mocked" one.

class InvoiceControllerSpec extends PlaySpec with GuiceOneAppPerSuite {

  val authMock: AuthAction = mock[AuthAction]
  val daoMock: InvoicerDao = mock[InvoicerDao]

  val underTest: InvoiceController = new InvoiceController(
    Helpers.stubControllerComponents(),
    authMock,
    daoMock
  )

  "InvoiceController" should {
    "should save invoice" in {
      val body =
        Source.fromResource("InvoiceControllerSaveInvoice.json").mkString.trim

      val request = FakeRequest(POST, "/saveInvoice")
        .withJsonBody(Json.toJson(body))

      val user = User("username", "password")
      val userRequestToResult = UserRequest(user, request)

      val userResult = Future{
        Ok("Authorized.")
      }

      when(authMock.invokeBlock(any, any)).thenReturn(userResult)

      val result: Future[Result] = underTest.saveInvoice.apply(
        request
      )

      status(result) mustBe 200
      contentAsString(result) mustBe "Invoice saved!"
    }
  }
}
0 Answers
Related