57

In my project I have to do some repository setup before all tests. This is done using some tricky static rules. However I've got no clue how to do clean up after all the tests. I don't want to keep some magic static number referring the number of all test methods, which I should maintain all the time.

The most appreciated way is to add some listener which would be invoked after all the tests. Is there any interface for it already in JUnit4?


edit: this has nothing to do with @BeforeClass and @AfterClass, cause I have to know if method annotated with @AfterClass is invoked for the last time.

1

5 Answers 5

59

I recommend to use org.junit.runner.notification.RunListener, example:

public class TestListener extends RunListener {
  @Override
  public void testRunStarted(Description description) throws Exception {
     // Called before any tests have been run.
  }
  @Override
  public void testRunFinished(Result result) throws Exception {
     // Called when all tests have finished
  }
}

Read more directly in JUnit java doc. You can use that even with Maven's surefire (unit tests) plugin or failsafe plugin (integration tests) by adding following code into plugin configuration:

<properties>
  <property>
    <name>listener</name>
    <value>com.innovatrics.afismq.it.TestListener</value>
  </property>
</properties>
4
  • 3
    I like this solution a lot better. You don't have to name all the classes Commented May 22, 2017 at 22:08
  • 2
    If you use this method, tear-down/clean-up will not occur when the tests are killed prematurely with [Ctrl] + [C]. See @Alexander's answer for a better solution that always performs clean up. Commented Oct 15, 2018 at 4:43
  • @stiemannkj1 And what if you stop the tests prematurely by killing the Java process itself? No solution is utterly guaranteed.
    – Ryan Lundy
    Commented Dec 24, 2018 at 11:20
  • @RyanLundy, nothing is guaranteed, sure. kill -9 will stop the java process without running the shutdown hook. But a shutdown hook is still much preferred to testRunFinished() when there's a possibility that the JVM will exit() before completing all tests. It will clean up in many more cases. Perhaps "always performs clean up" wasn't the best choice of words. This blog provides more info on when a shutdown hook will run: geeksforgeeks.org/jvm-shutdown-hook-java Commented Dec 25, 2018 at 4:04
54

I'm using JUnit 4.9. Will this help?:

import junit.framework.TestCase;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({First.class,Second.class,Third.class})
public class RunTestSuite extends TestCase {
    @BeforeClass
    public static void doYourOneTimeSetup() {
        ...
    }

    @AfterClass
    public static void doYourOneTimeTeardown() {
        ...
    }    
}

Edit: I am quite positive (unless I misunderstand your question) that my solution is what you are looking for. i.e. one teardown method after all your tests have ran. No listener required, JUnit has this facility. Thanks.

10
  • 1
    I'm pretty sure this will achieve your goal, unless I misunderstand your question. Commented Mar 28, 2012 at 9:11
  • 14
    I'd have to enumerate all the test classes (which is even now several, and the count will grow fast), so it's unfortunately non-acceptable Commented Mar 29, 2012 at 5:28
  • 1
    Sorry man, I simply do not know what you are trying to do. I have no idea why you have to enumerate anything. I suggest you put more detail into your question because, as it stands, it reads as though you want some static behaviour to be carried out at the end of your test run, after all your tests have run. That's all you have specified. If that was the case, then my solution does that. Please notice that I am NOT running AfterClass after each of your tests. I am using the AfterClass annotation on the AllTests. SO it will be called after All Tests. Maybe I just don't get it :) Commented Mar 29, 2012 at 20:24
  • 9
    Yeah, behaviour of this class is actually what I was looking for, however, this enumarating test classes in @SuiteClasses annotation is discarding this solution. I find it hard to maintain if there would be several test classes. I'm affraid there's not much to do in this subject, so thanks for your help. Commented Mar 31, 2012 at 11:26
  • 2
    If you don't want to have to enumerate your tests, you can do the same exact solution proposed here with ClasspathSuite (github.com/takari/takari-cpsuite) which uses classpath scanning to find tests Commented Mar 27, 2015 at 2:49
40

Just encountered the same problem.
My solution:

  • For a global set up: use (lazy) singleton to access something global that requires instantiation before the tests. The first test that accesses this singleton will trigger the global set up process.
  • For a global tear down: use a Java shutdown hook:
    Runtime.getRuntime().addShutdownHook(new Thread(() -> do_your_global_cleanup())));
1
  • This method is much better than either of the above answers since it will still perform the tear-down/clean-up when the tests are killed prematurely with [Ctrl] + [C]. For more details, check out my blog post. Commented Oct 15, 2018 at 4:38
0

You can always write your custom TestRunner. However, before you do that you need to evaluate the need for the same. It is better to use @BeforeClass and @AfterClass. Another example I can point to is, the fashion in which hibernate allows users to do unit testing using 'import.sql'.

-8

No need to use suite, just add @BeforeClass, and @AfterClass as static

public class Tests {

    @BeforeClass
    public static void doYourOneTimeSetup()
    {
        ...
    }

    @AfterClass
    public static void doYourOneTimeTeardown() {
        ...
    }    

    @Test
    public void testYourTestcase()
    {
        ...
    }
}
2
  • 9
    This does not work if you have more than one test class. Commented Jun 21, 2017 at 17:52
  • @DanielKaplan I did not have any issues with that - could you give an example of where this would not work ?
    – serup
    Commented Nov 10, 2020 at 13:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.