Search code examples
scalamockito-scala

Why is the return type correct if I'm not returning the Mock?


I have this trait which I mix in as needed in my test suites:

trait ValidationMock {

  def createValidationMock(result: Either[Error, Unit] = Right(())): Validation = {
    val validationMock = mock[Validation]

    validationMock.validateEligibility(any[Request], any[String])(any[Context]) returns result
  }
}

This compiles and test run successfully when instantiating this mock in the tests as:

val validationMock = createValidationMock()

But why does it work, if the validationMock mock created in the createValidationMock method is not being returned in the method?


Solution

  • But why does it work, if the validationMock mock created in the createValidationMock method is not being returned in the method?

    Because it is:

    • mockAction.returns returns ReturnAction[mockAction.type] (see code)
    • then apply returns ScalaOngoingStubbing[mockAction.type] (see code)
    • then implicit conversion extracts mock out of that value (see code) - pay attention that [T] in implicit conversion is the mock-type not the mocked call's result type

    So all of that is basically

    ScalaOngoingStubbing.toMock[Validation](
      new StubbingOps(
        validationMock.validateEligibility(any[Request], any[String])(any[Context])
      ) // this wrapper is probably erased by the macros
        .returns // ReturnAction[Either[Error, Unit]]
        .apply(result) // ScalaOngoingStubbing[Either[Error, Unit]]
    ) // Validation
    

    I wouldn't be surprised if toMock wasn't just extraction + some asInstanceOf on steroids.