Scala Mock Error

I’ve a piece of code:

case class User(name: String)
trait LoginService {
  def login(name: String, password: String): User
  def jog_in(name: String): String
}

class RealLoginService extends LoginService {
  def login(name: String, password: String) = {
    User(jog_in(name))
  }

  def jog_in(x: String) = {
       x
  }
}

Test case:

class LoginTest extends FunSuite with BeforeAndAfter with MockFactory {`

      test("test login service") {

val service: LoginService = mock[LoginService]

(service.jog_in( _: String))
  .expects(
    "johndoe"
  )
  .returns("johndoe")

val johndoe = service.login("johndoe", "secret")

assert(johndoe == User("johndoe"))

  }

}

I’am getting this error:

 Unexpected call: <mock-1> LoginService.login(johndoe, secret)

Expected:
inAnyOrder {
  <mock-1> LoginService.jog_in(johndoe) once (never called - UNSATISFIED)
}

Actual:
  <mock-1> LoginService.login(johndoe, secret)
ScalaTestFailureLocation: scala.Option at (Option.scala:121)
org.scalatest.exceptions.TestFailedException: Unexpected call: <mock-1> LoginService.login(johndoe, secret)

I understand its expecting jog_in call first, how to rectify this, Please help, Thanks.

The classical case for mocking is this: There’s a trait T and some entity (class/object/…) E that has a reference to an instance of T and calls methods on it. In the test case, you pass a mock instance of T to E and call methods on E, verifying through the mock that E issues the expected calls to T, and asserting that it produces the expected results from the mocked responses it receives from T.

In your scenario, there is no E. You are calling methods on a T mock directly, somehow expecting it to behave like some implementation of T that is never referenced by the test at all…

For contrast, consider this hypothetical class:

class LoginServiceClient(srv: LoginService) {
  def foo(name: String, password: String): Bar = {
    val user = srv.login(srv.jog_in(name), password)
    // compute some Bar from user
  }
}

In order to test LoginServiceClient independently of any concrete implementation of LoginService, you could pass it a mocked LoginService, expecting that, upon a call to #foo(), it receives calls to #jog_in() and #login() in that order, and finally asserting that the return value of the #foo() invocation is consistent with the mocked return values from #jog_in() and login().

1 Like

Thanks @sangamon, implemented as you suggested, working now. Thanks again