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