Alex Rivera | Logout

@parameters method is executed before @beforeclass method

Asked 2012-07-11T10:39:05.920
10

I'm using "parametrized" feature of junit 4 and I noticed that @parameters method is executed before @beforeclass method. This is creating a problem for me because the parameters i'm passing to the test cases via @parameters depends on the code initialize in the @beforeclass method. For example

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

Now, I'm initializing variable "initializeThis" to true in @beforeclass method but (surprisingly) when I executed the test case it prints

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

That is something not expected.
My question is; is there any way to execute the @beforeclass method before @parameters, can we do this is in junit 4?

Edit
Report

2 Answers

6

I would use just plain old java static {..} initializer instead of @BeforeClass, e.g.:

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

Only drawback I know is that classes inherited from this won't be able to override static initializer, while @BeforeClass gives some freedom in this aspect;

answered 2013-02-20T14:40:54.407
0

However, this does not work with TestSuites. Given

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

This does not work:

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

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

}

The output is

sets flag to late!
parameter=1

Nor that:

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

The output is "parameter=1". So the static initializer not executed at all. I found the following workaround. Extend "Suite" and insert the static initializer there:

public class TogglingSuite extends Suite {

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

    public TogglingSuite(Class<?> klass, Class<?>[] suiteClasses)
        throws Initialization
answered 2013-05-03T01:07:10.910

Your Answer