import java.util.function.Consumer
import spock.lang.Specification
class MySpec extends Specification {
def "type coercion does not work during interaction verification"() {
given:
Consumer good1 = Mock(Consumer)
Consumer good2 = Mock(Consumer)
Consumer good3 = Mock(Consumer)
Consumer good4 = Mock(Consumer)
Consumer bad = Mock(Consumer)
when:
good1.accept([])
good2.accept([] as Set)
good3.accept([] as Set)
good4.accept([] as Set)
bad.accept([] as Set)
then:
1 * good1.accept([])
1 * good2.accept(new HashSet([]))
1 * good3.accept(new LinkedHashSet([]))
1 * good4.accept({it == [] as Set})
1 * bad.accept([] as Set)
}
}
results in failure
Too few invocations for:
1 * bad.accept([] as Set) (0 invocations)
Unmatched invocations (ordered by similarity):
1 * bad.accept([])
One or more arguments(s) didn't match:
0: argument == expected
| | |
| | [] (java.util.ArrayList)
| false
[] (java.util.LinkedHashSet)
at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:98)
at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:77)
at MySpec.type coercion does not work during interaction verification(MySpec.groovy:19)
Spock version: 1.3-groovy-2.5.
Can you try with 2.0?
I fixed similar things, so with 2.0 this might already work as expected.
The issue still remains in the newest version that I can find in https://mvnrepository.com - 2.0-M3-groovy-2.5.
Too few invocations for:
1 * bad.accept([] as Set) (0 invocations)
Unmatched invocations (ordered by similarity):
1 * bad.accept([])
One or more arguments(s) didn't match:
0: argument == expected
| | |
| | [] (java.util.ArrayList)
| false
[] (java.util.LinkedHashSet)
at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:104)
at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:77)
at MySpec.type coercion does not work during interaction verification(MySpec.groovy:19)
Hmm, you seemed to miss 2.0-M4:

(I don't remember which version contains @Vampire fixes)
Not yet fixed in 2.0-M4-groovy-3.0:
Too few invocations for:
1 * bad.accept([] as Set) (0 invocations)
Unmatched invocations (ordered by similarity):
1 * bad.accept([])
One or more arguments(s) didn't match:
0: argument == expected
| | |
| | [] (java.util.ArrayList)
| false
[] (java.util.LinkedHashSet)
at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:104)
at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:77)
at MySpec.type coercion does not work during interaction verification(MySpec.groovy:19)
Thanks for checking.
Btw, not related with your question, but get know that some time ago I improved the mock creation syntax and currently you can just write:
Consumer good1 = Mock()
instead of:
Consumer good1 = Mock(Consumer)
and still doesn't have a warning in Idea.
Thanks for checking.
Btw, not related with your question, but get know that some time ago I improved the mock creation syntax and currently you can just write:
Consumer good1 = Mock()
instead of:
Consumer good1 = Mock(Consumer)
and still doesn't have a warning in Idea.
Thanks, will try to use it with 1.3, the version in my project! I use Eclipse, by the way.
Just interested, since which version did you improve mock creation syntax? I don't see warnings in Eclipse with 1.2, 1.3, 2.0.
This is a corner case of the argument matcher API.
Normally you'd write something like this:
1 * subscriber.receive(_ as String) // any non-null argument that is-a String
or in your case it would be 1 * bad.accept(_ as Set).
Spock transforms 1 * bad.accept([] as Set) into two distinct constraints: .addEqualArg([]).typeLastArg(java.util.Set) i.e. checking the type to be Set and testing it to be the same as the ArrayList, which fails of course.
The transform logic is here org.spockframework.compiler.InteractionRewriter#addArg.
However, changing this is not a super high priority as there are alternative ways to assert the same, which you already found.
1 * good.accept({it == [] as Set})
1 * good.accept({it.empty} as Set)
Just interested, since which version did you improve mock creation syntax? I don't see warnings in Eclipse with 1.2, 1.3, 2.0.
I've check it, and surprisingly, the commit was made over 5 years ago. Spock 1.1+.
I've created a potential fix for this special case, but there will still be many other cases where this won't apply.
So, should we create the special handling for the ListExpression or just keep it as it is for consistency?
WDYT @spockframework/supporter ?
Is this not a general issue with generic types?
Generally I think adding the special case is a good idea as collections are an extremely common use case.