2012-07-11 116 views
8

我使用junit 4的“参数化”功能,并且我注意到@parameters方法在@beforeclass方法之前执行。这对我造成了一个问题,因为我通过@parameters传递给测试用例的参数取决于@beforeclass方法中的代码初始化。例如@parameters方法在@beforeclass方法执行之前执行

@RunWith(Parameterized.class) 
public class TestOtherClass { 

    String argument; 
    private static boolean initializeThis; 

    public TestOtherClass(String parameter) throws Exception { 
     argument=parameter; 
    } 

    @BeforeClass 
    public static void doSetup() { 
     System.out.println("Doing setup before class..."); 
     initializeThis=true; // true or false, based on some condition 
    } 

    @Test 
    public void otherTest() { 
     System.out.println("Other test: " + argument); 
    } 

    @Parameters 
    public static Collection<Object[]> getData(){ 
     System.out.println("Inside parameter"); 
     String addThis; 
     if(initializeThis) 
      addThis="adding true"; 
     else 
      addThis="adding false"; 

     Object[] para1 = new Object[]{"First parameter :: " + addThis}; 
     Object[] para2 = new Object[]{"Second parameter :: " + addThis}; 

     Collection<Object[]> classNames = new ArrayList<Object[]>(); 
     classNames.add(para1); 
     classNames.add(para2); 
     return classNames; 
    } 
} 

现在,我初始化变量“initializeThis”为true @BeforeClass方法,但(奇怪),当我执行的测试情况下,打印

Other test: First parameter :: adding false 
Other test: Second parameter :: adding false 

这东西不期望。
我的问题是;有没有办法在@parameters之前执行@beforeclass方法,我们可以在junit 4中执行此操作吗?

+0

也许通过供应商功能以后可以检索的字段 – Kirby 2017-08-15 20:22:40

回答

1

JUnit为参数列表中的每个项目创建一个RunnerRunner是封装测试方法的东西。所以@Parameters将总是在@BeforeClass之前执行。

但是,您可以将@Parameterized与Assume结合使用。您总是将所有参数包含在列表中,无论您是否打算执行它。然后在测试方法中,添加assumeTrue(),其中测试值为initializeThis

@RunWith(Parameterized.class) 
public class TestOtherClassAssume { 
    private final String argument; 
    private final boolean initializeThisTest; 
    private static boolean initializeThis; 

    @Parameters 
    public static Collection<Object[]> getData(){ 
    System.out.println("Inside parameter"); 

    return Arrays.asList(new Object[][] { 
     { false, "First" }, 
     { true, "Second" }, 
    }); 
    } 

    public TestOtherClassAssume(boolean initializeThisTest, String argument) { 
    this.initializeThisTest = initializeThisTest; 
    this.argument = argument; 
    } 

    @BeforeClass 
    public static void doSetup() { 
    System.out.println("Doing setup before class..."); 
    initializeThis = true; // true or false, based on some condition 
    } 

    @Test 
    public void otherTest() { 
    Assume.assumeTrue(initializeThis == initializeThisTest); 
    System.out.println("Other test: " + argument); 
    } 
} 

从这个输出是:

Inside parameter 
Doing setup before class... 
Other test: Second 
5

我将只使用普通的旧式Java静态{..}初始化,而不是@BeforeClass,如:

@RunWith(Parameterized.class) 
public class TestOtherClass { 

    String argument; 
    private static boolean initializeThis; 

    public TestOtherClass(String parameter) throws Exception { 
     argument=parameter; 
    } 

    static { 
     doSetup(); 
    } 

    // @BeforeClass 
    public static void doSetup() { 
     System.out.println("Doing setup before class..."); 
     initializeThis=true; // true or false, based on some condition 
    } 

    @Test 
    public void otherTest() { 
     System.out.println("Other test: " + argument); 
    } 

    @Parameters 
    public static Collection<Object[]> getData(){ 
     System.out.println("Inside parameter"); 
     String addThis; 
     if(initializeThis) 
      addThis="adding true"; 
     else 
      addThis="adding false"; 

     Object[] para1 = new Object[]{"First parameter :: " + addThis}; 
     Object[] para2 = new Object[]{"Second parameter :: " + addThis}; 

     Collection<Object[]> classNames = new ArrayList<Object[]>(); 
     classNames.add(para1); 
     classNames.add(para2); 
     return classNames; 
    } 
} 

唯一的缺点我知道从这个继承来的类将无法重载静态初始化器,而@BeforeClass在这方面给了一些自由;

0

但是,这不适用于TestSuites。 鉴于

@RunWith(Parameterized.class) 
public class TogglableParameterizedTest { 
    static boolean useAllParameters = false; 

    int parameter; 

    public TogglableParameterizedTest(int parameter) { 
     super(); 
     this.parameter = parameter; 
    } 
    @Parameters 
    public static Collection<Object[]> getTestParameters() { 
     List<Object[]> parameters = new ArrayList<Object[]>(); 
     if(useAllParameters) { 
      parameters.add(new Object[] { 1 }); 
      parameters.add(new Object[] { 2 }); 
      parameters.add(new Object[] { 3 }); 
     } 
     else { 
      parameters.add(new Object[] { 1 }); 
     } 
     return parameters; 
    } 
    @Test 
    public void test() { 
     System.out.println("parameter=" + parameter); 
    } 
} 

这不起作用:

@RunWith(Suite.class) 
@SuiteClasses({ TogglableParameterizedTest.class }) 
public class NonWorkingTestSuite1 { 

    @BeforeClass 
    public static void toggle() { 
     System.out.println("sets flag to late!"); 
    } 

} 

输出是

sets flag to late! 
parameter=1 

也不是:

@RunWith(Suite.class) 
@SuiteClasses({ TogglableParameterizedTest.class }) 
public class NonWorkingTestSuite2 { 
    static { 
     System.out.println("sets flag still to late"); 
     TogglableParameterizedTest.useAllParameters = true; 
    } 
} 

的输出为 “参数= 1”。所以静态初始化器根本就没有执行。 我发现了以下解决方法。 扩展 “套房”,并插入静态初始化有:

public class TogglingSuite extends Suite { 

    static { 
     System.out.println("sets flag early enough!"); 
     TogglableParameterizedTest.useAllParameters = true; 
    } 

    public TogglingSuite(Class<?> klass, Class<?>[] suiteClasses) 
     throws InitializationError { 
     super(klass, suiteClasses); 
    } 

    public TogglingSuite(Class<?> klass, List<Runner> runners) 
     throws InitializationError { 
     super(klass, runners); 
    } 

    public TogglingSuite(Class<?> klass, RunnerBuilder builder) 
      throws InitializationError { 
     super(klass, builder); 
    } 

    public TogglingSuite(RunnerBuilder builder, Class<?> klass, 
      Class<?>[] suiteClasses) throws InitializationError { 
     super(builder, klass, suiteClasses); 
    } 

    public TogglingSuite(RunnerBuilder builder, Class<?>[] classes) 
      throws InitializationError { 
     super(builder, classes); 
    } 
} 

,并在您的测试套件使用:

@RunWith(TogglingSuite.class) 
@SuiteClasses({ TogglableParameterizedTest.class }) 
public class WorkingTestSuite { 

} 

输出是

sets flag early enough! 
parameter=1 
parameter=2 
parameter=3 

现在,它的工作原理。

4

这是一个老问题,但最近我有同样的问题。它让我觉得没有一种解决方案似乎适用于最明显的解决方法 - 在@Parameters方法中调用@BeforeClass方法。后者是静态的,只执行一次 - 在任何测试运行之前。所以,尽管它没有注释,但是所有的意图和目的都是@BeforeClass方法。更多详细信息可以在这里找到:http://feraldeveloper.blogspot.co.uk/2013/12/beforeclass-and-parametrized-junit-tests.html

+0

参数不幸的是,如果你的测试需要像'@ClassRule公共静态TemporaryFolder文件夹=新TemporaryFolder()这不起作用;'因为即使ClassRule在使用@Parameters(https://github.com/junit-team/junit4/issues/527)注解的方法之后被初始化, – 2017-03-10 06:07:15