I'd like to do something like this in jUnit:
@Runwith(Parameterized.class)
public abstract class BaseTest {
protected abstract List<Object[]> extraParams();
protected abstract ClassUnderTest testObject;
@Parameters
public Collection<Object[]> data() {
List<Object> params = ...; // a standard set of tests
params.addAll(extraParams());
return params;
}
@Test
public doTest() {
// assert things about testObject
}
}
public class ConcreteTest extends BaseTest {
protected ClassUnderTest = new ConcreteClass(...);
protected List<Object[]) extraParams() {
List<Object> extraParams = ...; // tests specific to this concrete type
return extraParams;
}
}
So that by extending this class, I run a bunch of standard tests against the object under test, plus some extra ones specified in the concrete class.
However, jUnit requires that the @Parameters method is static. How else can I tidily achieve the aim, of having a set of standard parameters plus extra ones in the concrete classes?
The best I've come up with so far is to have an un-annotated Collection<Object[]> standardParams() in the abstract class, and to require that the subclass contain a method:
@Parameters
public Collection<Object[]> data() {
List<Object> params = standardParams();
params.addAll(...); // extra params
return params;
}
... but this isn't as tidy as I'd like, as it puts too much responsibility on the writer of the subclass.
JUnit expects that the @Parameters method must be static and if you don't provide the static method, it throws No public static parameters method on class Exception.
But your requirement can be acheived by implementing org.junit.rules.TestRule as below:
BaseTest class
public abstract class BaseTest {
@Rule
public MyBaseTestRule myProjectTestRule = new MyBaseTestRule(data());
protected abstract List<Object[]> extraParams();
public List<Object[]> data() {
List<Object[]> listTotal = new ArrayList<>();
listTotal.addAll(extraParams());
//add your base test data here
return listTotal;
}
public abstract List<Object[]> extraParams();
}
ConcreteTest class
public class ConcreteTest extends BaseTest {
@Override
public List<Object[]> extraParams() {
List<Object[]> list = ...//set up data here
return list;
}
@Test
public void test1() {
Object[] testData = myProjectTestRule.getTestData();
//use the test data for the test
//Example: Assume addition of two integers scenario and data
//data[0] expectedresult, data[1],[2] inputs
//Assert.assertEquals((int)data[0], (int)(data[1]+data[2]));
}
//add other test cases
}
MyBaseTestRule class:
import java.util.List;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class MyBaseTestRule implements TestRule {
private final List<Object[]> totalTestData;
private final int totalTestsSize;
private int currentTestIndex;
public MyProjectTestRule(List<Object[]> list) {
this.totalTestsSize = list.size();
this.totalTestData = list;
}
public Object[] getTestData(){
return totalTestData.get(currentTestIndex);
}
@Override
public Statement apply(Statement stmt, Description desc) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
for(int i=0; i<totalTestsSize; i++) {
currentTestIndex = i;
stmt.evaluate();
}
}
};
}
}
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