Spock framework: matching wildcard arguments
Asked Answered
S

1

6

I am trying to write a Spock specification, where I want to verify a method that is being called with three arguments. I don't care about the first two at all, any instance of the argument types would do. I'm trying to use Spock wildcard argument matching but keep running into issues. My verification looks like this:

    when:
    packageUploadController.handleUpload(httpRequest)

    then: "the value of the 'dest' parameter is passed on to saveservice"
    saveService.saveImportPackage(_ as UploadedPackage, _ as PackageImportResponse.Builder)

Here saveService is a mock and UploadedPackage and PackageImportResponse.Builder are the expected arguments; I'm trying to get to a working test first before changing the code that calls saveService.

As far as I can see I'm doing this as documented, however the test fails with the following message:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: 
Cannot cast object '_' with class 'org.spockframework.lang.Wildcard' to 
class 'UploadedPackage' due to:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: 
UploadedPackage(org.spockframework.lang.SpreadWildcard)

I don't understand this message as it seems to indicate that my production code needs to provide a constructor taking a SpreadWildCard as an argument. What am I doing wrong here?

I also tried leaving the types out and just match on (_, _), however this also fails:

org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: 
SaveService$$EnhancerByCGLIB$$67b7324.saveImportPackage() is applicable for argument types: (org.spockframework.lang.Wildcard, org.spockframework.lang.Wildcard) values: [[*_], [*_]]

Here also I think I'm doing it as per the documentation, and don't understand why this fails (I added the types later to try and get rid of this error).

Sauternes answered 10/5, 2016 at 14:34 Comment(5)
Well, I think I have a solution, but can anyone explain why this works?? The saveImportPackage(_, _) method has a return type of void; when I change the verification to: saveService.saveImportPackage(_ as UploadedPackage, _ as PackageImportResponse.Builder) >> void The test goes green - why does the addition of the return type make the warning about the argument type go away??Sauternes
just to verify it seems that you pass in two arguments while you see you want to pass in 3, can this be the issue?Marsipobranch
Well spotted, but I'm trying to get to a working test for the two argument case first, then verification of a third argument should make the test fail, forcing me to add it to the code under test (I'm using TDD)Sauternes
If your method signature has three arguments, you have to pass three arguments.Kymry
I understand, but I'm working the other way around: I want a test to fail when I add the third argument, forcing me to add the argument to the method. But for that to happen I first want to see it work with two arguments.Sauternes
M
9

Put 1 * and then saveService.saveImportPackage(_ as UploadedPackage, _ as PackageImportResponse.Builder) this seems to work on a comparable case. Not completely clear why

 then: "the value of the 'dest' parameter is passed on to saveservice"
 1 * saveService.saveImportPackage(_ as UploadedPackage, _ as PackageImportResponse.Builder)
Marsipobranch answered 10/5, 2016 at 14:55 Comment(1)
The 1 * signifies that his mocked method will get called once per the "when" condition.Sumption

© 2022 - 2024 — McMap. All rights reserved.