问题
I cannot make compile Spock stub for generic class. The signature of constructor is following:
SomeClass(SerSup<Cap> capSup, String foo, String bar);
I need to stub the first argument. The following are my failed attempts.
First try:
def someClass = new SomeClass(Stub(SerSup<Cap>), "foo", "bar")
Error: Groovyc: unexpected token: >
Status bar: ',' or ')' expected
Another try:
def someClass = new someClass(Stub(Cup) as SerSup<Cup>, "foo" ,"bar")
groovy.lang.MissingMethodException: No signature of method: com.sun.proxy.$Proxy10.get() is applicable for argument types: () values: []
Possible solutions: grep(), getAt(java.lang.String), grep(java.lang.Object), wait(), any(), wait(long)
at loom.SomeClass.SomeMethod(SomeClassTest.groovy:14)
What is the right way to stub first argument of SomeClass
constructor?
回答1:
Your second attempt failed because you cannot cast Stub(Cap)
to SerSup<Cap>
. You would have to Stub(SerSup)
instead, or you could apply the suggestions I have described below.
I would recommend creating a variable for your stub before initializing SomeClass
. You can stub generic class using Stub(type: ...)
constructor, e.g.
SerSup<String> serSup = Stub(type: new TypeToken<SerSup<String>>(){}.type) as SerSup<String>
This initialization does not produce any warning in your IDE. If you are ok with some warnings you can simplify it to:
def serSup = Stub(type: new TypeToken<SerSup<String>>(){}.type)
Alternatively, you could try something like:
SerSup<String> serSup = Stub(SerSup) {
get() >> ""
}
This alternative solution requires stubbing methods to return valid type, otherwise it returns the equivalent of new Object()
. In the first case, "default" values are returned, because we satisfied all type checks (e.g. in case of a String
, an empty string returned).
Here is an example that shows both approaches:
import com.google.common.reflect.TypeToken
import spock.lang.Specification
class StubSpec extends Specification {
def "test stubbing with default value for String"() {
when:
SerSup<String> serSup = Stub(type: new TypeToken<SerSup<String>>(){}.type) as SerSup<String>
then:
serSup.get() == ""
}
def "test stubbing without explicit type"() {
when:
SerSup<String> serSup = Stub(SerSup) {
get() >> "lorem ipsum"
}
then:
serSup.get() == "lorem ipsum"
}
static class SerSup<T> {
private final T obj
SerSup(T t) {
this.obj = t
}
T get() {
return obj
}
}
}
来源:https://stackoverflow.com/questions/48263921/generics-with-spock-stub