How to verify mocked method call involving implicit arguments with matcher

3,209 views
Skip to first unread message

Oleg Aleshko

unread,
Apr 17, 2012, 8:47:05 PM4/17/12
to specs2...@googlegroups.com
Hi!

Let's say I have a class like this

class O {
def f[T : Numeric](a:String) = {
}
}

Is there a way to verify this method call (with specs2 1.9 mockito 1.9) ?

Currently this code

val o = mock[O]
o.f[Int]("")
got{
one(o).f[Int](===(""))
}

throws the following exception

Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.
 at Test$c$$anonfun$mockO$1.apply$mcV$sp(Test.scala:64)

Thanks, Oleg.

etorreborre

unread,
Apr 17, 2012, 9:06:46 PM4/17/12
to specs2...@googlegroups.com
Hi Oleg,

When you use matchers with Mockito, you have to use matchers for all parameters. So the following will work:

  • one(o).f[Int]("") // no need to specify the implicit parameter
  • one(o).f[Int](===(""))(===(implicitly[Numeric[Int]])) // all parameters are using matchers
Eric.

Oleg Aleshko

unread,
Apr 18, 2012, 7:12:48 AM4/18/12
to specs2...@googlegroups.com
Hi Eric.

This totally makes sense, I shouldn't have been coding late.
 Thanks for your help and brilliant work on specs!

However I've noticed that I still get the same exception if the method is
def f[T: Numeric](a: AnyRef)
and the test is
one(o).f[Int](===(""))(===(implicitly[Numeric[Int]]))

Also I can't seem to be able to much on null:

o.f[Int](null)
got {
one(o).f[Int](beNull[String])(===(implicitly[Numeric[Int]]))
}

throws

java.lang.Exception: The mock was not called as expected:
Argument(s) are different! Wanted:
o.f(
,

);
-> at com.saudipaypal.service.addfund.AddFundServiceImplTest$c$$anonfun$mockO$1.apply$mcV$sp(AddFundServiceImplTest.scala:70)
Actual invocation has different arguments:
o.f(
null,
scala.math.Numeric$IntIsIntegral$@acf31
);

Oleg.

etorreborre

unread,
Apr 18, 2012, 8:07:13 AM4/18/12
to specs2...@googlegroups.com
I think I know what's the issue, and here's a workaround:

  there was one(o).f[Int](argThat(===("")))(argThat(===(implicitly[Numeric[Int]])))

argThat encapsulates a specs2 matcher as a Hamcrest matcher so that it is registered by Mockito in the verification phase.

Unfortunately if, in your method, the parameter type is AnyRef, then the conversion, which is usually implicit, doesn't take place and the matcher is directly used as a parameter. So, to fix this, you have to do call the "argThat" method yourself.

Eric.

Your expression doesn't work because the type of the parameter

Andreas Fürer

unread,
Oct 10, 2013, 2:40:55 AM10/10/13
to specs2...@googlegroups.com
I'm trying to write a mock for the play webservice api (using implicit parameters).

Signature of method to mock:
def post [T] (body: T)(implicit wrt: Writeable[T], ct: ContentTypeOf[T]):
    Promise[Response]

This thread showed me that I have to explicitly specify all implicit parameters which I tried as follows:

import org.specs2.mock._
import org.mockito.internal.matchers._
import play.api.libs.ws.WS
import play.api.libs.ws.WS.WSRequestHolder
import play.api.libs.concurrent.Execution.Implicits._
import play.api.http.Writeable
import play.api.http.ContentTypeOf

case class GrooveWSMock() extends Mockito {
  val grooveWSRequestHolder: WSRequestHolder = mock[WSRequestHolder]
  val grooveWSResponse: play.api.libs.ws.Response = mock[play.api.libs.ws.Response]

  grooveWSResponse.status returns 200
  grooveWSResponse.body returns "BODY RESP FROM GROOVE"

  val futureResponse = scala.concurrent.Future { grooveWSResponse }

  grooveWSRequestHolder.post(any[Map[String,Seq[String]]])(argThat(===(implicitly[Writeable[Map[String,Seq[String]]]])), argThat(===(implicitly[ContentTypeOf[Map[String,Seq[String]]]]))) returns futureResponse

}

However, that results in a compilation error 

GrooveWSMock.scala:23: not found: value ===

What is the correct import for the === matcher?

-Andreas

etorreborre

unread,
Oct 10, 2013, 7:29:26 PM10/10/13
to specs2...@googlegroups.com
Hi Andreas,

You need to import org.specs2.matcher.AnyMatchers._ or more generally org.specs2.matcher.Matchers._

E.
Reply all
Reply to author
Forward
0 new messages