I've got an abstract generic collections class GCollection, and a class that extends that called GStack.
To test the implementation I have an abstract JUnit test class, which I extend for each of the GCollection implementations I do:
public abstract class GCollectionTest<T extends GCollection<E>, E> {
private GCollection<? extends Object> collection;
protected abstract GCollection<T> createInstance();
@Before
public void setup() throws Exception {
collection = createInstance();
}
// Tests down here.
This is extended like so:
public class GStackCollectionInterfaceTest<S extends GCollection<E>> {
protected GDSStack<? extends Object> createInstance() {
return new GDSStack<String>();
}
}
I test first with a GStack holding String objects, then re-run the tests with Date objects to ensure it works with different object types.
@Test
public void testIsEmpty() {
assertTrue(collection.isEmpty()); // Fresh Stack should hold no objects
collection.add(new String("Foo")); // Error here.
assertFalse(collection.isEmpty());
}
The error given is:
The method add(capture#24-of ? extends Object) in the type GCollection is not applicable for the arguments (String)
My understanding of the error is that I can't put a String object into a GCollection<T extends GCollection<E>> object, but I don't think that's what I'm trying to do.
How can I solve this error while maintaining tests that are as generic as possible?
The type of collection is GCollection<? extends Object>. It is not possible to add anything to this collection, see: can't add value to the java collection with wildcard generic type.
There's no need for wildcards or bounds in the subclass so you can simplify the generics. Something like:
abstract class GCollectionTest<T> {
protected Collection<T> collection;
protected abstract Collection<T> createCollection();
protected abstract T createObject();
@Before
public void setup() throws Exception {
collection = createCollection();
}
@Test
public void testIsEmpty() {
assertTrue(collection.isEmpty());
collection.add(createObject());
assertFalse(collection.isEmpty());
}
}
class GStackCollectionInterfaceTest extends GCollectionTest<String> {
protected GDSStack<String> createCollection() {
return new GDSStack<String>();
}
protected String createObject() {
return new String("123");
}
}
Using different types with the collection is allowed because of the generic type, and checked by the compiler, so it doesn't really need testing. I would just test the different container types, but you could create another subclass that uses Date instead of String.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With