mardi 22 décembre 2015

Writing test for recoverWith in Scala

I have following business logic in service layer which use two brokers to call external services to get the info. On broker I am catching some exception types and converting to custom exceptions either RetryException or NoRetryException.

def fetchMyCount(firstParam: String, secondParam: String): Future[WSResponse] = {
  val firstStepResponse = myFirstBroker.fetchFirstInfo(firstparam)
  firstStepResponse.flatMap { firstResponse =>
    mySecondBroker.fetchSecondInfo(secondParam, firstResponse)
  }.recoverWith(exceptionHandler())
}

Then to controller I am sending Future.failed(ex) as below:

def exceptionHandler(): PartialFunction[Throwable,Future[WSResponse]] = {
  case ex: NoRetryException =>
    logger.error("No retry exception", ex)
    Future.failed(ex)
  case ex: RetryException =>
    logger.error("Retry exception", ex)
    Future.failed(ex)
}

Right now I have following test

test("Should return NoRetry message if first call success but second call failed") { 
  val mockFirstResponse = mock[WSResponse]   
  val secondCallExceptionResponse: Future[WSResponse] = Future.failed(new NoRetryException("fail-msg", new Throwable()))

  when(firstBroker.fetchFirstInfo(firstParam)).thenReturn(Future(mockFirstResponse)
  when(secondBroker.fetchSecondInfo(secondParam, mockFirstResponse)).thenReturn(secondCallExceptionResponse)

  val response = myService.fetchMyCount(firstParam, secondParam)

  whenReady(response.failed) { exception =>
    verify(firstBroker).fetchFirstInfo(firstParam)
    assert(exception.isInstanceOf[NoRetryException])
  }
}

I am feeling this is not a correct way to test recoverwith(). Here I can change secondCallExceptionResponse to return any Exception type and assert that type to make test pass without changing any service code.

For example if I want to add 'Exception` type (which i am not catching till now) catch in broker. I can change test as follow and make it pass without making changes to service.

val secondCallExceptionResponse: Future[WSResponse] = Future.failed(new Exception("fail-msg", new Throwable()))
.....
assert(exception.isInstanceOf[Exception])

Any suggestion on how to test recoverWith()?

Aucun commentaire:

Enregistrer un commentaire