2016-10-28 3 views
4

내가 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; 
    } 
} 

즉, 내가 개체에 대한 표준 테스트의 무리에서 실행 테스트와 콘크리트 클래스에 지정된 몇 가지 추가 테스트가 포함됩니다.

그러나 jUnit은 @Parameters 메소드가 정적이어야합니다. 그 밖의 방법으로 표준 클래스 세트에 구체적인 클래스를 추가하는 것 외에 목표를 정돈 할 수 있습니까?

내가 지금까지 가지고 올 것 중에 최고는 않은 주석이 추상 클래스에 Collection<Object[]> standardParams(), 서브 클래스는 방법을 포함 할 것을 요구해야하는 것입니다 ...

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

을하지만,이 ISN을 나는 서브 클래스의 작가에게 너무 많은 책임을 맡기 때문에 내가 원했던만큼 깔끔하지는 않다.

+0

슬림 : 당신이 내 대답에 모습을 가질 수 있습니까? – developer

+0

@ javaguy 미안하지만 시간이 좀 걸렸습니다. 주말이었습니다. – slim

답변

2

JUnit은 @Parameters 메서드가 정적이어야하며 정적 메서드를 제공하지 않으면 No public static parameters method on class Exception을 반환합니다.

그러나 귀하의 요구 사항은 다음과 org.junit.rules.TestRule 구현하여 을 acheived 할 수 있습니다

BaseTest 클래스

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 클래스를

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 클래스 :

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

감사합니다. 만약 내가 올바르게 이해한다면, 우리는'@RunWith (Parameterized.class) '를 사용하는 대신에 "같은 테스트를 반복적으로 실행"프레임 워크를 구현하려고합니다. 하지만'evaluate()'이 실행될 때마다'data()'의 어떤 항목이 사용되는지'@ Test' 메소드가 어떻게 알 수 있는지 설명 할 수 있습니까? – slim

+0

@slim 도움이 되었다면 내 대답을 수락 할 수 있습니까? – developer

+0

누군가가 발명을 덜 수반하는 무언가를 생각해내는 경우를 대비하여 일주일을드립니다. 기분을 상하게하지 마십시오. 때로는 사람들이 내 대답을 받아들이는 것이 더 성급하지 않다고 말해야합니다. – slim