问题
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