I'm using scalamock to mock this class:
class HttpService {
def post[In, Out]
(url: String, payload: In)
(implicit encoder: Encoder[In], decoder: Decoder[Out])
: Future[Out] = ...
...
}
...so my test class has a mock used like this:
val httpService = mock[HttpService]
(httpService.post[FormattedMessage, Unit](_ : String, _ : FormattedMessage) (_ : Encoder[FormattedMessage], _: Decoder[Unit]))
.expects("http://example.com/whatever",*, *, *)
.returning(Future.successful(()))
Apparently I have to write the whole mock function signature. If I only put the underscores in the signature, without the corresponding types, I get errors like this one:
[error] missing parameter type for expanded function ((x$1: <error>, x$2, x$3, x$4) => httpService.post[FormattedMessage, Unit](x$1, x$2)(x$3, x$4))
[error] (httpService.post[FormattedMessage, Unit](_, _) (_, _))
^
What I don't like about this code is that the mock expectation is used in several places in the tests and this ugly signature is repeated all over the place but with different In/Out type parameters and expectations.
So I thought I would write a class
class HttpServiceMock extends MockFactory {
val instance = mock[HttpService]
def post[In, Out] = instance.post[In, Out](_ : String, _ : In) (_ : Encoder[In], _: Decoder[Out])
}
...and use it like this:
val httpService = new HttpServiceMock()
...
httpService.post[FormattedMessage, Unit]
.expects("http://example.com/whatever",*, *, *)
.returning(Future.successful(()))
...which compiles fine but when I run the tests I get the following error:
java.lang.NoSuchMethodException: com.myapp.test.tools.HttpServiceMock.mock$post$0()
at java.lang.Class.getMethod(Class.java:1786)
at com.myapp.controllers.SlackControllerSpec.$anonfun$new$3(SlackControllerSpec.scala:160)
at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
at org.scalatest.Transformer.apply(Transformer.scala:22)
at org.scalatest.Transformer.apply(Transformer.scala:20)
at org.scalatest.WordSpecLike$$anon$1.apply(WordSpecLike.scala:1078)
at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
How can I fix this error? Are there other ways to avoid the re-writing of the mocked function signature over and over again?
UPDATE: In the end the mock looks like this:
trait HttpServiceMock extends MockFactory {
object httpService {
val instance = mock[HttpService]
def post[In, Out] = toMockFunction4(instance.post[In, Out](_: String, _: In)(_: Encoder[In], _: Decoder[Out]))
}
}