What order are the Junit @Before/@After called?

前端 未结 6 1421
不思量自难忘°
不思量自难忘° 2020-12-07 15:27

I have an Integration Test Suite. I have a IntegrationTestBase class for all my tests to extend. This base class has a @Before (public void s

相关标签:
6条回答
  • 2020-12-07 15:40

    You can use @BeforeClass annotation to assure that setup() is always called first. Similarly, you can use @AfterClass annotation to assure that tearDown() is always called last.

    This is usually not recommended, but it is supported.

    It's not exactly what you want - but it'll essentially keep your DB connection open the entire time your tests are running, and then close it once and for all at the end.

    0 讨论(0)
  • 2020-12-07 15:42

    I think based on the documentation of the @Before and @After the right conclusion is to give the methods unique names. I use the following pattern in my tests:

    public abstract class AbstractBaseTest {
    
      @Before
      public final void baseSetUp() { // or any other meaningful name
        System.out.println("AbstractBaseTest.setUp");
      }
    
      @After
      public final void baseTearDown() { // or any other meaningful name
        System.out.println("AbstractBaseTest.tearDown");
      }
    }
    

    and

    public class Test extends AbstractBaseTest {
    
      @Before
      public void setUp() {
        System.out.println("Test.setUp");
      }
    
      @After
      public void tearDown() {
        System.out.println("Test.tearDown");
      }
    
      @Test
      public void test1() throws Exception {
        System.out.println("test1");
      }
    
      @Test
      public void test2() throws Exception {
        System.out.println("test2");
      }
    }
    

    give as a result

    AbstractBaseTest.setUp
    Test.setUp
    test1
    Test.tearDown
    AbstractBaseTest.tearDown
    AbstractBaseTest.setUp
    Test.setUp
    test2
    Test.tearDown
    AbstractBaseTest.tearDown
    

    Advantage of this approach: Users of the AbstractBaseTest class cannot override the setUp/tearDown methods by accident. If they want to, they need to know the exact name and can do it.

    (Minor) disadvantage of this approach: Users cannot see that there are things happening before or after their setUp/tearDown. They need to know that these things are provided by the abstract class. But I assume that's the reason why they use the abstract class

    0 讨论(0)
  • 2020-12-07 15:50

    Yes, this behaviour is guaranteed:

    @Before:

    The @Before methods of superclasses will be run before those of the current class, unless they are overridden in the current class. No other ordering is defined.

    @After:

    The @After methods declared in superclasses will be run after those of the current class, unless they are overridden in the current class.

    0 讨论(0)
  • 2020-12-07 15:55

    This isn't an answer to the tagline question, but it is an answer to the problems mentioned in the body of the question. Instead of using @Before or @After, look into using @org.junit.Rule because it gives you more flexibility. ExternalResource (as of 4.7) is the rule you will be most interested in if you are managing connections. Also, If you want guaranteed execution order of your rules use a RuleChain (as of 4.10). I believe all of these were available when this question was asked. Code example below is copied from ExternalResource's javadocs.

     public static class UsesExternalResource {
      Server myServer= new Server();
    
      @Rule
      public ExternalResource resource= new ExternalResource() {
          @Override
          protected void before() throws Throwable {
              myServer.connect();
             };
    
          @Override
          protected void after() {
              myServer.disconnect();
             };
         };
    
      @Test
      public void testFoo() {
          new Client().run(myServer);
         }
     }
    
    0 讨论(0)
  • 2020-12-07 16:00

    If you turn things around, you can declare your base class abstract, and have descendants declare setUp and tearDown methods (without annotations) that are called in the base class' annotated setUp and tearDown methods.

    0 讨论(0)
  • 2020-12-07 16:03

    One potential gotcha that has bitten me before:

    I like to have at most one @Before method in each test class, because order of running the @Before methods defined within a class is not guaranteed. Typically, I will call such a method setUpTest().

    But, although @Before is documented as The @Before methods of superclasses will be run before those of the current class. No other ordering is defined., this only applies if each method marked with @Before has a unique name in the class hierarchy.

    For example, I had the following:

    public class AbstractFooTest {
      @Before
      public void setUpTest() { 
         ... 
      }
    }
    
    public void FooTest extends AbstractFooTest {
      @Before
      public void setUpTest() { 
        ...
      }
    }
    

    I expected AbstractFooTest.setUpTest() to run before FooTest.setUpTest(), but only FooTest.setupTest() was executed. AbstractFooTest.setUpTest() was not called at all.

    The code must be modified as follows to work:

    public void FooTest extends AbstractFooTest {
      @Before
      public void setUpTest() {
        super.setUpTest();
        ...
      }
    }
    
    0 讨论(0)
提交回复
热议问题