53

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.

dedek
  • 7,981
  • 3
  • 38
  • 68
Mateusz Chromiński
  • 2,742
  • 4
  • 28
  • 45
  • A clean **TestNG** solution can be found here: http://stackoverflow.com/a/26381858/1857897 – dedek Jul 15 '15 at 06:52

5 Answers5

55

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>
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
Juraj Michalak
  • 1,138
  • 10
  • 9
  • 3
    I like this solution a lot better. You don't have to name all the classes – committedandroider May 22 '17 at 22:08
  • 1
    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](https://stackoverflow.com/questions/9903341/cleanup-after-all-junit-tests#49448319) for a better solution that always performs clean up. – stiemannkj1 Oct 15 '18 at 04:43
  • @stiemannkj1 And what if you stop the tests prematurely by killing the Java process itself? No solution is utterly guaranteed. – Ryan Lundy Dec 24 '18 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: https://www.geeksforgeeks.org/jvm-shutdown-hook-java/ – stiemannkj1 Dec 25 '18 at 04: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.

HellishHeat
  • 2,280
  • 4
  • 31
  • 37
  • 1
    I'm pretty sure this will achieve your goal, unless I misunderstand your question. – HellishHeat Mar 28 '12 at 09:11
  • 13
    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 – Mateusz Chromiński Mar 29 '12 at 05: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 :) – HellishHeat Mar 29 '12 at 20:24
  • I'm not used to use suites and TestCase, so it's probably my misunderstand;). But if it is what you say, then how about this line: @SuiteClasses({First.class,Second.class,Third.class}) ? Isn't it enumerating all the classes, of which tests should be finished to trigger desired cleanup method? – Mateusz Chromiński Mar 30 '12 at 08:06
  • 1
    Think of a Test Suite as a house for all your tests. So inside First.java you may have many tests (@Test), or, indeed, First.java may be a TestSuite itself. Above, RunTestSuite is badly named, the traditional name for that would be 'AllTests'. Anyway, yes, you are correct, to say that all of the tests found in First....Third will be finished before doYourOneTimeTeardown() is execued. That's what you wanted thought, right? – HellishHeat Mar 31 '12 at 09:10
  • 8
    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. – Mateusz Chromiński Mar 31 '12 at 11:26
  • 1
    Is it possible to run only a single `TestCase` in this case? Or do I have to run always the whole `TestSuite`? Can this solution be easily integrated with a build tool (e.g. Maven's surefire) without additional setup? – dedek Oct 16 '14 at 08:03
  • 2
    If you don't want to have to enumerate your tests, you can do the same exact solution proposed here with ClasspathSuite (https://github.com/takari/takari-cpsuite) which uses classpath scanning to find tests – NamshubWriter Mar 27 '15 at 02:49
  • for same functionality without needing to enumerate the tests, see @serup's answer below: http://stackoverflow.com/a/38264405/1663987 – simpleuser Mar 06 '17 at 01:43
  • 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](https://stackoverflow.com/questions/9903341/cleanup-after-all-junit-tests#49448319) for a better solution that always performs clean up. – stiemannkj1 Oct 15 '18 at 04:43
36

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())));
Alexander
  • 2,761
  • 1
  • 28
  • 33
  • 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](http://stiemannkj1.gitlab.io/use-Runtime-addShutdownHook-instead-of-RunListener-testRunFinished/). – stiemannkj1 Oct 15 '18 at 04: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'.

questzen
  • 3,260
  • 18
  • 21
-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()
    {
        ...
    }
}
serup
  • 3,676
  • 2
  • 30
  • 34