I am currently writing unit tests related to GET requests, here below is a parameterized test that take a generic type E.
abstract class AbstractEntityTest< E extends Entity > {
@ParameterizedTest( name = "[{index}]: {2}" )
@MethodSource( "RoleDataProvider#provideIntArgsToTest" )
void testIntRequestsThatReturnSingle( String fileName, Integer requestParam, String testName, int index )
// do something
}
}
What I want to do is to dynamically change the method source in function of the actual type of E at runtime.
Example:
public class AnimalTest extends AbstractEntityTest< Animal > {
... }
Here E is type Animal so I would like to change the @MethodSource to
@MethodSource( "AnimalDataProvider#provideIntArgsToTest" )
Is there any way to do it ? I've been searching for hours to no avail...
That isn't going to be possible in Java I'm afraid. Java is a strongly, statically typed language, which means that objects can't change their type and type checking occurs during compilation.
Java implements generics with erasure, which means that the compiler will replace your bound type parameter E
with bounding class Entity
, (described here).
What are you trying to achieve? If you want to avoid duplication, you could group shared logic into a single method and call it @BeforeEach
for example.
EDIT: Gotcha, I think I know what you mean, cheers for the response. Have you tried specifying that in the children test classes?
I tried messing around with the same concept but with Number
, Integer
, and Double
. Here's what I got:
AbstractTest.java
public abstract class AbstractTest<E extends Number> {
void testIntRequestsThatReturnSingle(Number i){
System.out.println(i);
//doing the same stuff here but with the different data sources
}
public static IntStream intProvider() {
return IntStream.range(0, 10);
}
public static DoubleStream doubleProvider() {
return DoubleStream.of(0.0,1.1,2.2);
}
}
One child IntTest.java
class:
public class IntTest extends AbstractTest<Integer>{
@ParameterizedTest
@MethodSource( "intProvider" )
public void intTest(Number i){
this.testIntRequestsThatReturnSingle(i);
}
}
Another child DoubleTest.java
class:
public class DoubleTest extends AbstractTest<Integer>{
@ParameterizedTest
@MethodSource( "doubleProvider" )
public void doubleTest(Number i){
this.testIntRequestsThatReturnSingle(i);
}
}
This way you can minimise duplication and ensure that the right methods are called for the right classes (without any scary casting). Is this something along the lines of what you were looking for?