Junit - run set up method once

JavaJunit

Java Problem Overview


I set up a class with a couple of tests and rather than using @Before I would like to have a setup method that executes only once before all tests. Is that possible with Junit 4.8?

Java Solutions


Solution 1 - Java

Although I agree with @assylias that using @BeforeClass is a classic solution it is not always convenient. The method annotated with @BeforeClass must be static. It is very inconvenient for some tests that need instance of test case. For example Spring based tests that use @Autowired to work with services defined in spring context.

In this case I personally use regular setUp() method annotated with @Before annotation and manage my custom static(!) boolean flag:

private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
    if (setUpIsDone) {
        return;
    }
    // do the setup
    setUpIsDone = true;
}

Solution 2 - Java

You can use the BeforeClass annotation:

@BeforeClass
public static void setUpClass() {
    //executed only once, before the first test
}

Solution 3 - Java

JUnit 5 now has a @BeforeAll annotation:

> Denotes that the annotated method should be executed before all @Test > methods in the current class or class hierarchy; analogous to JUnit > 4’s @BeforeClass. Such methods must be static.

The lifecycle annotations of JUnit 5 seem to have finally gotten it right! You can guess which annotations available without even looking (e.g. @BeforeEach @AfterAll)

Solution 4 - Java

When setUp() is in a superclass of the test class (e.g. AbstractTestBase below), the accepted answer can be modified as follows:

public abstract class AbstractTestBase {
    private static Class<? extends AbstractTestBase> testClass;
    .....
    public void setUp() {
        if (this.getClass().equals(testClass)) {
            return;
        }

        // do the setup - once per concrete test class
        .....
        testClass = this.getClass();
    }
}

This should work for a single non-static setUp() method but I'm unable to produce an equivalent for tearDown() without straying into a world of complex reflection... Bounty points to anyone who can!

Solution 5 - Java

Edit: I just found out while debugging that the class is instantiated before every test too. I guess the @BeforeClass annotation is the best here.

You can set up on the constructor too, the test class is a class after all. I'm not sure if it's a bad practice because almost all other methods are annotated, but it works. You could create a constructor like that:

public UT () {
    // initialize once here
}
@Test
// Some test here...

The ctor will be called before the tests because they are not static.

Solution 6 - Java

Use Spring's @PostConstruct method to do all initialization work and this method runs before any of the @Test is executed

Solution 7 - Java

JUnit 5 @BeforeAll can be non static provided the lifecycle of the test class is per class, i.e., annotate the test class with a @TestInstance(Lifecycle.PER_CLASS) and you are good to go

Solution 8 - Java

Try this solution: https://stackoverflow.com/a/46274919/907576 :

with @BeforeAllMethods/@AfterAllMethods annotation you could execute any method in Test class in an instance context, where all injected values are available.

Solution 9 - Java

My dirty solution is:

public class TestCaseExtended extends TestCase {

    private boolean isInitialized = false;
    private int serId;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        if(!isInitialized) {
            loadSaveNewSerId();
            emptyTestResultsDirectory();
            isInitialized = true;
        }
    }

   ...

}

I use it as a base base to all my testCases.

Solution 10 - Java

If you don't want to force a declaration of a variable that is set and checked on each subtest, then adding this to a SuperTest could do:

public abstract class SuperTest {

    private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
    protected final boolean initialized() {
        final boolean[] absent = {false};
        INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
            return absent[0] = true;
        });
        return !absent[0];
    }
}



public class SubTest extends SuperTest {
    @Before
    public void before() {
        if ( super.initialized() ) return;

         ... magic ... 
    }

}

Solution 11 - Java

I solved this problem like this:

Add to your Base abstract class (I mean abstract class where you initialize your driver in setUpDriver() method) this part of code:

private static boolean started = false;
static{
    if (!started) {
        started = true;
        try {
            setUpDriver();  //method where you initialize your driver
        } catch (MalformedURLException e) {
        }
    }
}

And now, if your test classes will extends from Base abstract class -> setUpDriver() method will be executed before first @Test only ONE time per run.

Solution 12 - Java

After experimenting for some time this is my solution. I needed this for spring boot test. I tried using @PostConstruct, unfortunately it is executed for every test.

public class TestClass {
    private static TestClass testClass = null;
    @Before
    public void setUp() {
        if (testClass == null) {
            // set up once
            ...
            testClass = this;
        }
    }
    @AfterClass
    public static void cleanUpAfterAll() {
        testClass.cleanUpAfterAllTests();
    }
    private void cleanUpAfterAllTests() {
        // final cleanup after all tests
        ...
    }
    @Test
    public void test1() {
        // test 1
        ...
    }
    @Test
    public void test2() {
        // test 2
        ...
    }
}

Solution 13 - Java

Here is one alternative suggestion:

What I do to get this working is Create a method named _warmup or just _ Annotate the test class with @FixMethodOrder(MethodSorters.NAME_ASCENDING)

This is applicable only if you run all tests in the class

It has a downside of having additional test included, which will also run one additional @Before and @After It is usually advised for your test methods to be order independent, this breaks that rule, but why someone would like tests ordered randomly in the reports I have no clue so NAME_ASCENDING is what I always use

But the upsides to this is simple setup with minimal code and without the need to extend classes/runners etc... Test run lengths are more accurate since all setup time is reported on method _warmup

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBober02View Question on Stackoverflow
Solution 1 - JavaAlexRView Answer on Stackoverflow
Solution 2 - JavaassyliasView Answer on Stackoverflow
Solution 3 - JavaBrianView Answer on Stackoverflow
Solution 4 - JavaSteve ChambersView Answer on Stackoverflow
Solution 5 - Javauser5692355View Answer on Stackoverflow
Solution 6 - JavaAbhishek ChatterjeeView Answer on Stackoverflow
Solution 7 - JavaDeepakView Answer on Stackoverflow
Solution 8 - JavaradistaoView Answer on Stackoverflow
Solution 9 - JavaObi TwoView Answer on Stackoverflow
Solution 10 - JavamjsView Answer on Stackoverflow
Solution 11 - JavaSergiiView Answer on Stackoverflow
Solution 12 - Javauser123456789View Answer on Stackoverflow
Solution 13 - JavaIgor ČordašView Answer on Stackoverflow