2

I am trying to write some functional tests, and I want to mock a service that consumes an external provider. But I can not set up the mock for the functions that return EitherT

This is the Trait whose implementation call the external service

@ImplementedBy(classOf[ExternalServiceImpl])
trait ExternalService {
  def index: EitherT[Future, String, JsValue]
}

In the CustomAppPerSuite trait I set up

val mockExternalService = mock[ExternalService]

 implicit override lazy val app = new GuiceApplicationBuilder()
.in(Mode.Test)
.overrides(bind[ExternalService].toInstance(mockExternalService))
.build()

val externalService = app.injector.instanceOf[ExternalService]

Then When I try to mock the succesful response

  "ExternalController#index" should {

    "return index data" in {
      doReturn(EitherT.rightT(Json.parse("""{"key": "value"}""")).when(externalService).index
      val fakeRequest = FakeRequest(GET, "/api/external")
      val result = externalController.index().apply(fakeRequest)
      status(result) mustBe OK
    }

But I get this error

[error]  found   : cats.data.EitherT[cats.package.Id,Nothing,JsValue]
[error]  required: cats.data.EitherT[scala.concurrent.Future,String,JsValue]
[error]   def index = EitherT.rightT(

I only want to mock the successful response, because it is what I am testing. Is there a way to do this?

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
agusgambina
  • 6,229
  • 14
  • 54
  • 94

2 Answers2

3

With mockito-scala-cats you could write that in a much more succint way

Json.parse("""{"key": "value"}""") willBe returnedF by externalService.index
//or
externalService.index shouldReturnF Json.parse("""{"key": "value"}""")

The library will look at the return type of externalService.index and get the appropiate cats.Applicative(s) to make this work smoothly.

Another advantage if you're running on Scalatest is that you can mix-in ResetMocksAfterEachTest and get all the mocks you wired into the play fake app to be automatically reset before each test.

Check here for more details

ultrasecr.eth
  • 1,437
  • 10
  • 13
2

Try helping the compiler out by providing some type parameters to rightT like so

EitherT.rightT[Future, String](Json.parse("""{"key": "value"}"""))

instead of

EitherT.rightT(Json.parse("""{"key": "value"}"""))
Mario Galic
  • 47,285
  • 6
  • 56
  • 98