Junit @ Before / @之后叫什么命令?

我有一个集成testing套件。 我有一个IntegrationTestBase类,用于扩展我所有的testing。 这个基类有一个@Beforepublic void setUp() )和@Afterpublic void tearDown() )方法来build立API和数据库连接。 我一直在做的就是覆盖每个testing用例中的这两个方法,并调用super.setUp()super.tearDown() 。 然而,如果有人忘记叫超级或把它们放在错误的地方,抛出exception,并忘记在最后或者其他地方调用super,那么这可能会导致问题。

我想要做的是在基类finalsetUptearDown方法,然后添加我们自己的注释@Before@After方法。 做一些初始testing,它总是按照这个顺序调用:

 Base @Before Test @Before Test Test @After Base @After 

但我只是有点担心,顺序不能保证,可能会导致问题。 我环顾四周,没有看到有关这个问题的任何事情。 有谁知道我是否可以做到这一点,没有任何问题?

码:

 public class IntegrationTestBase { @Before public final void setUp() { *always called 1st?* } @After public final void tearDown() { *always called last?* } } public class MyTest extends IntegrationTestBase { @Before public final void before() { *always called 2nd?* } @Test public void test() { *always called 3rd?* } @After public final void after() { *always called 4th?* } } 

是的,这个行为是有保证的:

@Before

超类的@Before方法将在当前类的前面运行,除非它们在当前类中被覆盖。 没有其他顺序被定义。

@After

在超类中@After方法将在当前类的那些之后运行,除非它们在当前类中被覆盖。

之前曾经咬过我的一个潜在问题:

我喜欢在每个testing类中至多有一个@Before方法,因为不能保证运行在类中定义的@Before方法的顺序。 通常我会调用setUpTest()方法。

但是,尽pipe@Before被logging为The @Before methods of superclasses will be run before those of the current class. No other ordering is defined. The @Before methods of superclasses will be run before those of the current class. No other ordering is defined. ,这仅适用于每个标有@Before方法在类层次结构中具有唯一的名称。

例如,我有以下几点:

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

我期望AbstractFooTest.setUpTest()FooTest.setUpTest()之前运行,但只执行FooTest.setupTest()AbstractFooTest.setUpTest()根本没有被调用。

代码必须修改如下工作:

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

我认为基于@Before和@的文档正确的结论是赋予方法独特的名称。 我在testing中使用以下模式:

 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"); } } 

 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"); } } 

作为结果

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

这种方法的优点:AbstractBaseTest类的用户不能意外覆盖setUp / tearDown方法。 如果他们想,他们需要知道确切的名字,可以做到。

(小)这种方法的缺点:用户不能看到他们的setUp / tearDown之前或之后有事情发生。 他们需要知道这些东西是由抽象类提供的。 但我认为这就是他们使用抽象类的原因

如果你把东西转过来,你可以声明你的基类抽象,并有后代声明setUp和tearDown方法(没有注释),在基类的注释setUp和tearDown方法中调用。

您可以使用@BeforeClass注释来确保始终首先调用setup() 。 同样,你可以使用@AfterClass注释来确保tearDown()总是最后被调用。

通常不build议这样做,但支持 。

这不完全是你想要的 – 但它将基本上保持你的数据库连接在你的testing运行的整个过程中保持打开状态,然后在最后一次closures它。

这不是对口号问题的回答,但它是问题主体中提到的问题的答案。 不要使用@Before或@After,而要使用@ org.junit.Rule,因为它给了你更多的灵活性。 如果您正在pipe理连接, ExternalResource (从4.7开始)是您最感兴趣的规则。 另外,如果你想保证你的规则的执行顺序使用RuleChain (从4.10开始)。 我相信当问这个问题时,所有这些都是可用的。 下面的代码示例是从ExternalResource的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); } }