Argument capture issue with an empty list?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Argument capture issue with an empty list?

Jeff
I'm mocking a setter method on an object that just takes a single argument of the type List.  The setter method is invoked with empty lists plenty of times, and sometimes the list is populated.  I'm using an underscore as my argument matcher in the interaction definition.

_ * foo.setBars(_) >> {
  map
.put id, it
}

id is defined in the scope above it, within an enclosing mock.

It looks like the Spock framework is interpreting that as a vararg invocation of the method and giving me an Arrays$ArrayList instance, with an empty ArrayList as the first element, at least when an empty List is used when setBars is invoked.  Is this the intended behavior, and is it avoidable/preventable?  I'd like the matcher to give me an empty list, rather than the Arrays$ArrayList with an empty ArrayList as the only element.

I'm using Spock 1.0-groovy-2.4 with Groovy 2.4.5 on Java 8. Any insight would be appreciated!

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Argument capture issue with an empty list?

Marcin Zajączkowski
On 2016-05-24 04:43, Jeff wrote:

> I'm mocking a setter method on an object that just takes a single argument
> of the type List.  The setter method is invoked with empty lists plenty of
> times, and sometimes the list is populated.  I'm using an underscore as my
> argument matcher in the interaction definition.
>
> _ * foo.setBars(_) >> {
>   map.put id, it
> }
>
> id is defined in the scope above it, within an enclosing mock.
>
> It looks like the Spock framework is interpreting that as a vararg
> invocation of the method and giving me an Arrays$ArrayList instance, with
> an empty ArrayList as the first element, at least when an empty List is
> used when setBars is invoked.  Is this the intended behavior, and is it
> avoidable/preventable?  I'd like the matcher to give me an empty list,
> rather than the Arrays$ArrayList with an empty ArrayList as the only
> element.

I'm not sure if I understood you correctly, but in the aforementioned
example I would expect `it` to be a list with an empty list as the first
(and the only one) element.

`it` is an array of input arguments passed to the method. It is quite a
common mistake to assume that in a case of one method argument `it` will
be just that argument. However, it is always needed to use `it[0]` to
get that argument. Alternatively you may want to explicitly define input
parameters in a closure:

_ * foo.setBars(_) >> { List inputList ->
  map.put id, inputList
}

Is it something you were asking about?

Marcin

P.S. Quite by accident that confusion with input parameters will be one
of the nooks and crannies covered during my upcoming presentation at
Gr8Conf.eu - http://gr8conf.eu/#/talk/325 ;)


>
> I'm using Spock 1.0-groovy-2.4 with Groovy 2.4.5 on Java 8. Any insight
> would be appreciated!
>


--
http://blog.solidsoft.info/ - Working code is not enough

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Argument capture issue with an empty list?

Jeff
I think you've understood me correctly, Marcin.  Thanks for your response!  However, typing the inputList as a List doesn't change the behavior, since it still ends up being an Arrays$ArrayList instance with a single element of an ArrayList, which has the actual list that was passed to foo.setBars() method.

In other cases, where there is a single-argument method, using the underscore returns the actual element, not an array of arguments to the method.  For a single argument that is a collection, I suppose it'd be tough to know exactly what the interaction is saying should be matched.  I'd still like to see the underscore return the single argument (even if it's a list), and a matcher of *_ return the arguments themselves in a list.

Is it documented somewhere that methods that have a single argument of a List/Set type return an ArrayList of arguments when the underscore matcher is used in the interaction?  If it is, I've missed it...

On Tuesday, May 24, 2016 at 3:17:50 PM UTC-4, Marcin Zajączkowski wrote:
On 2016-05-24 04:43, Jeff wrote:

> I'm mocking a setter method on an object that just takes a single argument
> of the type List.  The setter method is invoked with empty lists plenty of
> times, and sometimes the list is populated.  I'm using an underscore as my
> argument matcher in the interaction definition.
>
> _ * foo.setBars(_) >> {
>   map.put id, it
> }
>
> id is defined in the scope above it, within an enclosing mock.
>
> It looks like the Spock framework is interpreting that as a vararg
> invocation of the method and giving me an Arrays$ArrayList instance, with
> an empty ArrayList as the first element, at least when an empty List is
> used when setBars is invoked.  Is this the intended behavior, and is it
> avoidable/preventable?  I'd like the matcher to give me an empty list,
> rather than the Arrays$ArrayList with an empty ArrayList as the only
> element.

I'm not sure if I understood you correctly, but in the aforementioned
example I would expect `it` to be a list with an empty list as the first
(and the only one) element.

`it` is an array of input arguments passed to the method. It is quite a
common mistake to assume that in a case of one method argument `it` will
be just that argument. However, it is always needed to use `it[0]` to
get that argument. Alternatively you may want to explicitly define input
parameters in a closure:

_ * foo.setBars(_) >> { List inputList ->
  map.put id, inputList
}

Is it something you were asking about?

Marcin

P.S. Quite by accident that confusion with input parameters will be one
of the nooks and crannies covered during my upcoming presentation at
Gr8Conf.eu - <a href="http://gr8conf.eu/#/talk/325" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fgr8conf.eu%2F%23%2Ftalk%2F325\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFRzpk55Mz2X3Dgx87hU7Xtj6jlrA&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fgr8conf.eu%2F%23%2Ftalk%2F325\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFRzpk55Mz2X3Dgx87hU7Xtj6jlrA&#39;;return true;">http://gr8conf.eu/#/talk/325 ;)


>
> I'm using Spock 1.0-groovy-2.4 with Groovy 2.4.5 on Java 8. Any insight
> would be appreciated!
>


--
<a href="http://blog.solidsoft.info/" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fblog.solidsoft.info%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHrYfQZXf28IldRj4DW21JQvByDPg&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fblog.solidsoft.info%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHrYfQZXf28IldRj4DW21JQvByDPg&#39;;return true;">http://blog.solidsoft.info/ - Working code is not enough

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Argument capture issue with an empty list?

Marcin Zajączkowski
On 2016-05-24 22:09, Jeff wrote:

> I think you've understood me correctly, Marcin.  Thanks for your response!
>  However, typing the inputList as a List doesn't change the behavior, since
> it still ends up being an Arrays$ArrayList instance with a single element
> of an ArrayList, which has the actual list that was passed to foo.setBars()
> method.
>
> In other cases, where there is a single-argument method, using the
> underscore returns the actual element, not an array of arguments to the
> method.  For a single argument that is a collection, I suppose it'd be
> tough to know exactly what the interaction is saying should be matched.
>  I'd still like to see the underscore return the single argument (even if
> it's a list), and a matcher of *_ return the arguments themselves in a list.
>
> Is it documented somewhere that methods that have a single argument of a
> List/Set type return an ArrayList of arguments when the underscore matcher
> is used in the interaction?  If it is, I've missed it...

class PersonDao {
    Person save(Person element)
}

dao.save(_) >> { it }

It will not work (will fail with GroovyCastException) as "it" will be a
list (Arrays$ArrayList) with one Person element. For me it is quite
consistent, but can be confusing for the first time. I haven't met a
situation where the real argument is passed to a closure unless the type
is clearly defined (like in my first code sample).

I have to admit that I haven't run my example with a list as a named
Closure parameter and in fact it doesn't work correctly. I haven't dug
into source code, but it can be confusing for Spock to distinguish a
situation where you expect the first argument of a list type to be
passed as a closure parameter or a list of all input arguments. In can
be somehow confusing for the user, so you may want to make a PR to the
documentation:
https://github.com/spockframework/spock/blob/master/docs/interaction_based_testing.adoc#computing-return-values

Marcin


>
> On Tuesday, May 24, 2016 at 3:17:50 PM UTC-4, Marcin Zajączkowski wrote:
>>
>> On 2016-05-24 04:43, Jeff wrote:
>>> I'm mocking a setter method on an object that just takes a single
>> argument
>>> of the type List.  The setter method is invoked with empty lists plenty
>> of
>>> times, and sometimes the list is populated.  I'm using an underscore as
>> my
>>> argument matcher in the interaction definition.
>>>
>>> _ * foo.setBars(_) >> {
>>>   map.put id, it
>>> }
>>>
>>> id is defined in the scope above it, within an enclosing mock.
>>>
>>> It looks like the Spock framework is interpreting that as a vararg
>>> invocation of the method and giving me an Arrays$ArrayList instance,
>> with
>>> an empty ArrayList as the first element, at least when an empty List is
>>> used when setBars is invoked.  Is this the intended behavior, and is it
>>> avoidable/preventable?  I'd like the matcher to give me an empty list,
>>> rather than the Arrays$ArrayList with an empty ArrayList as the only
>>> element.
>>
>> I'm not sure if I understood you correctly, but in the aforementioned
>> example I would expect `it` to be a list with an empty list as the first
>> (and the only one) element.
>>
>> `it` is an array of input arguments passed to the method. It is quite a
>> common mistake to assume that in a case of one method argument `it` will
>> be just that argument. However, it is always needed to use `it[0]` to
>> get that argument. Alternatively you may want to explicitly define input
>> parameters in a closure:
>>
>> _ * foo.setBars(_) >> { List inputList ->
>>   map.put id, inputList
>> }
>>
>> Is it something you were asking about?
>>
>> Marcin
>>
>> P.S. Quite by accident that confusion with input parameters will be one
>> of the nooks and crannies covered during my upcoming presentation at
>> Gr8Conf.eu - http://gr8conf.eu/#/talk/325 ;)
>>
>>
>>>
>>> I'm using Spock 1.0-groovy-2.4 with Groovy 2.4.5 on Java 8. Any insight
>>> would be appreciated!
>>>
>>
>>
>> --
>> http://blog.solidsoft.info/ - Working code is not enough
>>
>>
>


--
http://blog.solidsoft.info/ - Working code is not enough

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/d/optout.
Loading...