11

Junit's @BeforeClass and @AfterClass must be declared static. There is a nice workaround here for @BeforeClass. I have a number of unit tests in my class and only want to initialize and clean up once. Any help on how to get a workaround for @AfterClass? I'd like to use Junit without introducing additional dependencies. Thanks!

Community
  • 1
  • 1
jamesw1234
  • 338
  • 4
  • 18
  • 1
    What is stopping you from using static methods to set up and tear down? True, the state that you set up would have to be moved to static fields, but it sounds like you want it to have static scope. – Hank D May 07 '16 at 01:53
  • Save the test instance in a `static` field. Access it in your `@AfterClass` method and have it invoke whatever clean up method you want. – Sotirios Delimanolis May 07 '16 at 02:00
  • There are other classes that access the same clean up method that requires different scopes – jamesw1234 May 07 '16 at 17:34
  • 1
    Sounds like you should refactor the setup and teardown methods into a [JUnit Rule](https://github.com/junit-team/junit4/wiki/Rules). Then you can have tests which use it in a static context and tests which use it in a non-static context. – sisyphus May 08 '16 at 16:32
  • Did you ever find an answer to this question? – DevelopingDeveloper May 12 '17 at 16:07
  • I found the solution to my problem [here](http://stackoverflow.com/questions/11392692/autowired-in-static-classes) – DevelopingDeveloper May 12 '17 at 16:13

1 Answers1

4

If you want something similar to the workaround mentioned for @BeforeClass, you could keep track of how many tests have been ran, then once all tests have been ran finally execute your ending cleanup code.

public class MyTestClass {
  // ...
  private static int totalTests;
  private int testsRan;
  // ...

  @BeforeClass
  public static void beforeClass() {
    totalTests = 0;
    Method[] methods = MyTestClass.class.getMethods();
    for (Method method : methods) {
      if (method.getAnnotation(Test.class) != null) {
        totalTests++;
      }
    }
  }

  // test cases...

  @After
  public void after() {
    testsRan++;
    if (testsRan == totalTests) {
       // One time clean up code here...
    }
  }
}

This assumes you're using JUnit 4. If you need to account for methods inherited from a superclass, see this as this solution does not get inherited methods.

kingkupps
  • 3,284
  • 2
  • 16
  • 28
  • this might work in simple cases but won't work if tests are ignored, or in inherited tests – dkatzel Feb 26 '18 at 03:39
  • @dkatzel Good point. You could also iterate through the inherited methods by doing something like [this](https://stackoverflow.com/questions/28400408/what-is-the-new-way-of-getting-all-methods-of-a-class-including-inherited-defau). It's probably best to keep resources that should only be cleaned up once as static and take care of it during `@AfterClass`. – kingkupps Feb 26 '18 at 03:50