0

I am having difficulty in getting a test to work using Spock Framework in a Java project. I have the following:

 - Person.class 
 - Attribute.class 

I have a service class which is being mocked in my test. The method I am trying to mock has the following signature:

serviceClass.call(Map<Person, List<Attribute>> map)

When I mock it purely using wildcards like:

serviceClass.call(_) >> MockReturnObject

Everything works as expected. The call in the service class will return the MockReturnObject.

However, for my specific case I need to specify the Person object I am passing in and assign it a specific MockReturnObject. Like:

serviceClass.call([(PersonA):_)]) >> MockReturnObjectA

or

def listWildcard = _
serviceClass.call(Map.of(PersonA, listWildcard)) >> MockReturnObjectA

Neither of these approaches work and the call ends up returning null instead of MockReturnObjectA (I assume it is because it is failing to match the arguments). I am unfortunately not too experienced with Spock and my attempt to search through documentation on handling Maps in this scenario has not come up fruitful. I would appreciate anyone able to offer any guidance.

I don't think it makes a difference but PersonA is passed in to an entry method in the serviceClass in a list like;

List<Attribute> list = getAttributeList() 

entryClass.process(List<Person> personList) {
        personList.forEach(person -> serviceClass.call(Map.of(person, list))
   }

So in my tests, the "when" is:

entryClass.process([PersonA, PersonB, PersonC])

With all 3 being Mock(Person.class) with their own behaviours.

pillow
  • 39
  • 6
  • Unfortunately not, this returns: Groovy.lang.MissingMethodException: No signature of method:com.sun.proxy.$Proxy14.call() is applicable for argument types: (org.spockframework.lang.Wildcard, org.spockframework.lang.Wildcard) values: [[*_], [*_]] I remove the "as Person" from the end and it goes back to working but obviously then I cannot vary the response based on what I pass into call(). – pillow Oct 09 '21 at 07:38

1 Answers1

1

When you use an object as parameter Spock will use Groovy equality to compare the argument. However, if it is too complicated to construct the reference object, you can use code argument constraints instead to programmatically check the actual argument.

serviceClass.call({ it[PersonA] == attributeList }) >> MockReturnObject

As you've shared very little code this is the best example I can give.

Leonard Brünings
  • 12,408
  • 1
  • 46
  • 66
  • This is a very suitable alternative for my use case. I can verify the map argument contains a particular key and provide the corresponding mock response. Thank you very much for your insight. – pillow Oct 12 '21 at 09:40