Search code examples
scalaunit-testingscalatestscalamock

Do we need to test a failure scenario of a public method which fails with an Exception?


I have a case class Employee defined as case class Employee(.........fields.....) I have a method say

def getEmployees(organization: String): Future[Seq[Employee]] = {
   val result = employeeClient.getAllEmployees(organization)

   // some logic on this list of Employees received from the 
   client and manipulate it to get  finalListOfEmployees and return it 
   to caller of `getEmployees`//

  finalListOfEmployees

//end //
}

Now I test getEmployees using scala mock. I am not handling exception coming from getEmployees or not recovering from it. That means Exception appearing at getAllEmployees of client method will be traveling back to the caller of getEmployees.

Now the question is do we need to test this aspect ?

I meant does the following test add any value ??

"Fail with future" in {  (mockEmployeeClient.getAllEmployees_).expects("SomeOrganization").returning(Future.failed(new Exception("failed"))
          getEmployees("SomeOrganization).failed.futureValue.getMessage shouldBe "failed"
}

Solution

  • I think we should test it because the semantics here seem to be the callers of getEmployees expect failures to be represented by a failed Future. Now consider what would happen if someone would refactor getEmployees such that the failures in employeeClient.getAllEmployees(organization) are recovered by returning an empty list Future(Nil) instead like so

    def getEmployees(organization: String): Future[Seq[Employee]] = {
     val result = employeeClient.getAllEmployees(organization)
     result.recover { case e => List.empty[Employee] }
     ...
    }
    

    Everything would compile fine like before, but suddenly the semantics are quite different. A unit test could catch this change in semantics, and prompt us to either remove the refactoring or update callers of getEmployees appropriately.