2012-07-11 11 views
8

Estoy usando la función "parametrizada" de junit 4 y noté que el método @parameters se ejecuta antes del método @beforeclass. Esto me crea un problema porque los parámetros que paso a los casos de prueba a través de @parameters dependen del código de inicialización en el método @beforeclass. Por ejemploEl método @parameters se ejecuta antes del método @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; 
    } 
} 

ahora, estoy inicializar "initializeThis" variables de cierto en el método @beforeclass pero (sorprendentemente) cuando ejecuta el caso de prueba se imprime

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

Eso es algo que no se esperaba.
Mi pregunta es; ¿hay alguna forma de ejecutar el método @beforeclass antes de @parameters, podemos hacer esto en el junit 4?

+0

Quizás pase las funciones del proveedor para los parámetros que pueden recuperar los campos más tarde – Kirby

Respuesta

1

JUnit crea un Runner para cada elemento en la lista de parámetros, un Runner es lo que encapsula el método de prueba. Por lo tanto, el @Parameters siempre se ejecutará antes que @BeforeClass.

Sin embargo, puede combinar @Parameterized con Assume. Siempre incluye todos los parámetros en su lista, sin importar si tiene la intención de ejecutarlos. Luego, en el método de prueba, agregue el assumeTrue() que prueba contra el valor 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); 
    } 
} 

El resultado de esto es:

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

me gustaría utilizar simplemente vieja estática de Java {..} inicializador en lugar de @BeforeClass, por ejemplo:

@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; 
    } 
} 

único inconveniente que saber es que las clases heredadas de esto no podrán anular el inicializador estático, mientras que @BeforeClass da cierta libertad en este aspecto;

0

Sin embargo, esto no funciona con TestSuites. Dada

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

esto no funciona:

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

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

} 

la salida es

sets flag to late! 
parameter=1 

Ni que:

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

La salida es "parámetro = 1". Entonces el inicializador estático no se ejecutó en absoluto. He encontrado la siguiente solución. Extender "Suite" e inserte el inicializador estático allí:

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

y utilizarlo en su conjunto de pruebas:

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

} 

La salida es

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

Ahora funciona.

4

Esta es la vieja pregunta, pero tuve el mismo problema recientemente. Me sorprende que ninguna de las soluciones vaya por la solución más obvia: llamar al método @BeforeClass en el método @Parameters. Este último es estático y se ejecuta solo una vez, antes de ejecutar cualquiera de las pruebas. Por lo tanto, es para todos los efectos un método @BeforeClass aunque no esté anotado como tal. Más detalles se pueden encontrar aquí: http://feraldeveloper.blogspot.co.uk/2013/12/beforeclass-and-parametrized-junit-tests.html

+0

Desafortunadamente, esto no funciona si su prueba requiere algo como '@ClassRule public static Carpeta temporalFolder = new TemporaryFolder();' ya que incluso la ClassRule se inicializa después del método anotado con @Parameters (https://github.com/junit-team/junit4/issues/527) –

Cuestiones relacionadas