Search code examples
scalaplayframeworkmockitoscalatestmockito-scala

Mockito: 0 matchers expected, 1 recorded


I have the folliwng PlaySpec:

"Service A" must {

   "do the following" in {
       val mockServiceA = mock[ServiceA]
       val mockServiceB = mock[ServiceB]
       when(mockServiceA.applyRewrite(any[ClassA])).thenReturn(resultA) // case A
       when(mockServiceB.execute(any[ClassA])).thenReturn(Future{resultB})

       // test code continuation
   }
} 

The definition of ServiveA and ServiceB are

class ServiceA {
    def applyRewrite(instance: ClassA):ClassA = ???
}

class ServiceB {
   def execute(instance: ClassA, limit: Option[Int] = Some(3)) = ???
}

Mocking ServiceA#applyRewrite works perfectly. Mocking ServiceB#execute fails with the following exception:

Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at RandomServiceSpec.$anonfun$new$12(RandomServiceSpec.scala:146)

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"));

Although the instructions included in the exception seem a bit counterintuitive to me I have tried the following:

when(mockServiceB.execute(anyObject[ClassA])).thenReturn(Future{resultB})
when(mockServiceB.execute(anyObject())).thenReturn(Future{resultB})
when(mockServiceB.execute(anyObject)).thenReturn(Future{resultB})
when(mockServiceB.execute(any)).thenReturn(Future{resultB})
when(mockServiceB.execute(any, Some(3))).thenReturn(Future{resultB})
when(mockServiceB.execute(any[ClassA], Some(3))).thenReturn(Future{resultB})

All unfortunately to no avail. The only thing that changes is the number of expected and recorded matchers the exception refers to.

The weirdest thing for me though is that the mocking works perfectly for case A.


Solution

  • Use the idiomatic syntax of mockito-scala and all the stuff related to the default argument will be deal with by the framework

    mockServiceB.execute(*) returns Future.sucessful(resultB)
    

    if you add the cats integration it could reduce to just

    mockServiceB.execute(*) returnsF resultB
    

    more info here