i am writing a integration test framework for my java application and i run into one issue i am not able to fix. Please let me explain:
The following code snippets are simplified classes for better visibility:
I got the following abstract class:
public abstract class AbstractTestModel<T extends AbstractTestModel> {
public T doSomething(){
return getThis();
}
public T getThis(){
return (T) this;
}
public <U extends AbstractTestModel<T>> U as(Class<U> type){
AbstractTestModel<T> obj = this;
if (obj.getClass().isAssignableFrom(type)){
return type.cast(obj);
}else{
throw new AssertionError("This (" + obj.getClass().getName() +")could not be resolved to the expected class " + type.getName());
}
}
}
And there are may concrete classes like this:
public class ConcreteTestModel1 extends AbstractTestModel<ConcreteTestModel1> {
public void doSomethingElse(){
}
}
I also wrote a Factory class. This factory downloads a JSON object from the server and instantiates one of the concret classes - depending on the JSON response. This concrete classes have many helper methods for testing the JSON response. The thing is, that the factory method always returns an "AbstractTestModel".
The integration test looks like this (simplified):
public class SomeTest {
TestModelFactory testModelFactory;
@Before
public void init(){
testModelFactory = new TestModelFactory();
}
@Test
public void someTest(){
AbstractTestModel anyModel = testModelFactory.createModel("someIdOfTheServer");
//ERROR: this does not work! Cannot resolve method doSomethingElse():
anyModel.doSomething().as(ConcreteTestModel1.class).doSomethingElse();
//as() method returns AbstractTestModel instead of ConcreteTestModel1
//this works:
AbstractTestModel as = anyModel.as(ConcreteTestModel1.class);
//this does not work:
ConcreteTestModel1 asConcreteTestModel1 = anyModel.as(ConcreteTestModel1.class);
}
}
The method as(Class type) should check if the given class is valid, cast "this" to the desired class and return it, but it always returns the AbstractTestModel.
If I make the "as" method static or if i get rid of the generic class like this...
public abstract class AbstractTestModel {
/*
Not possible to return the superclass anymore
public T doSomething(){
return getThis();
}
public T getThis(){
return (T) this;
}
*/
public <U extends AbstractTestModel> U as(Class<U> type){
AbstractTestModel obj = this;
if (obj.getClass().isAssignableFrom(type)){
return type.cast(obj);
}else{
throw new AssertionError("This (" + obj.getClass().getName() +")could not be resolved to the expected class " + type.getName());
}
}
}
... then it works fine, but of course i am not able to return the concrete class in all other methods any more.
Thank you for reading this long post. Do you know what am i doing wrong here? Is there a solution for that?
Thank you for any tip and have a nice day!
Manuel