Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type coercion does not work during interaction verification #1260

Closed
monrealis opened this issue Jan 15, 2021 · 11 comments · Fixed by #1261
Closed

Type coercion does not work during interaction verification #1260

monrealis opened this issue Jan 15, 2021 · 11 comments · Fixed by #1261

Comments

@monrealis
Copy link

monrealis commented Jan 15, 2021

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.

@monrealis monrealis changed the title Type coersion does not work during interaction verification Type coercion does not work during interaction verification Jan 15, 2021
@Vampire
Copy link
Member

Vampire commented Jan 15, 2021

Can you try with 2.0?
I fixed similar things, so with 2.0 this might already work as expected.

@monrealis
Copy link
Author

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)

@szpak
Copy link
Member

szpak commented Jan 15, 2021

Hmm, you seemed to miss 2.0-M4:
image
(I don't remember which version contains @Vampire fixes)

@monrealis
Copy link
Author

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)

@szpak
Copy link
Member

szpak commented Jan 16, 2021

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.

@monrealis
Copy link
Author

monrealis commented Jan 16, 2021

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.

@monrealis
Copy link
Author

monrealis commented Jan 17, 2021

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.

@leonard84
Copy link
Member

leonard84 commented Jan 17, 2021

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)

@szpak
Copy link
Member

szpak commented Jan 17, 2021

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+.

@leonard84
Copy link
Member

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 ?

@mkutz
Copy link
Contributor

mkutz commented Jan 18, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants