参数化jUnit测试中的继承(或替代方法)

sli*_*lim 5 java junit parameterized

我想在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;
     }
}
Run Code Online (Sandbox Code Playgroud)

因此,通过扩展此类,我针对被测对象运行了一系列标准测试,以及具体类中指定的一些额外测试。

但是,jUnit要求该@Parameters方法是静态的。我还能如何巧妙地达到在具体的类中拥有一组标准参数和额外参数的目标?

到目前为止,我想出的最好的办法是Collection<Object[]> standardParams()在抽象类中添加一个未注释的对象,并要求子类包含一个方法:

 @Parameters
 public Collection<Object[]> data() {
     List<Object> params = standardParams();
     params.addAll(...); // extra params
     return params;
 }
Run Code Online (Sandbox Code Playgroud)

...但是这并不像我想要的那样整洁,因为它给子类的作者带来了太多的责任。

dev*_*per 2

JUnit 期望 @Parameters 方法必须是静态的,如果您不提供静态方法,它将抛出No public static parameters method on class Exception

但是您的要求可以通过实现 org.junit.rules.TestRule 来实现,如下所示:

基础测试类

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();
}
Run Code Online (Sandbox Code Playgroud)

具体测试类

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
}
Run Code Online (Sandbox Code Playgroud)

MyBaseTestRule 类:

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();
            }
         }
       };
    }
}
Run Code Online (Sandbox Code Playgroud)