2012-07-11 19 views
8

Utilizzo la funzione "parametrizzata" di junit 4 e ho notato che il metodo @parameters viene eseguito prima del metodo @beforeclass. Questo mi crea un problema perché i parametri che sto passando ai casi di test tramite @parameters dipendono dal codice inizializzato nel metodo @beforeclass. Per esempioIl metodo @parameters viene eseguito prima del metodo @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; 
    } 
} 

Ora, io sono l'inizializzazione "initializeThis" variabile a true nel metodo @beforeclass ma (sorprendentemente) quando ho eseguito il test case si stampa

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

Questo è qualcosa che non previsto.
La mia domanda è; c'è un modo per eseguire il metodo @beforeclass prima di @parameters, possiamo farlo in junit 4?

+0

forse passare le funzioni del fornitore per i parametri che possono recuperare i campi successivamente – Kirby

risposta

1

JUnit crea un Runner per ogni elemento nell'elenco dei parametri, un codice Runner incapsula il metodo di prova. Quindi @Parameters verrà sempre eseguito prima di @BeforeClass.

Tuttavia, è possibile combinare il parametro @Parameterized con Assume. Includete sempre tutti i parametri nel vostro elenco, anche se non intendete eseguirlo. Quindi, nel metodo di prova, aggiungere lo assumeTrue() che verifica il valore 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); 
    } 
} 

L'output di questo è:

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

userei semplicemente vecchio statico java {..} inizializzazione invece di @BeforeClass, ad esempio:

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

inconveniente Solo io so che le classi ereditate da questo non saranno in grado di sovrascrivere l'inizializzatore statico, mentre @BeforeClass dà una certa libertà in questo aspetto;

0

Tuttavia, questo non funziona con TestSuites. Dato

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

Questo non funziona:

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

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

} 

L'uscita è

sets flag to late! 
parameter=1 

Né che:

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

L'uscita è "parametro = 1". Quindi l'inizializzatore statico non è stato eseguito affatto. Ho trovato la seguente soluzione alternativa. Estendere "Suite" e inserire l'inizializzatore statico c'è:

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

e utilizzarlo nella vostra suite di test:

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

} 

L'uscita è

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

Ora funziona.

4

Questa è una vecchia domanda ma ho avuto lo stesso problema di recente. Mi sembra che nessuna delle soluzioni sembri andare alla soluzione più ovvia: chiamare il metodo @BeforeClass nel metodo @Parameters. Quest'ultimo è statico e viene eseguito una sola volta, prima che uno qualsiasi dei test sia stato eseguito. Quindi, è a tutti gli effetti un metodo @BeforeClass anche se non è annotato come tale. Maggiori dettagli possono essere trovati qui: http://feraldeveloper.blogspot.co.uk/2013/12/beforeclass-and-parametrized-junit-tests.html

+0

Sfortunatamente questo non funziona se il test richiede qualcosa come '@ClassRule public static TemporaryFolder folder = new TemporaryFolder();' come anche il ClassRule viene inizializzato dopo il metodo annotato con @Parameters (https://github.com/junit-team/junit4/issues/527) –

Problemi correlati