Inheritance (or an alternative) in Parameterized jUnit tests

java, junit, parameterized

Solution

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();
            }
         }
       };
    }
}

Problem

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.

Original source