Junit @ Before / @之后叫什么命令?
我有一个集成testing套件。 我有一个IntegrationTestBase
类,用于扩展我所有的testing。 这个基类有一个@Before
( public void setUp()
)和@After
( public void tearDown()
)方法来build立API和数据库连接。 我一直在做的就是覆盖每个testing用例中的这两个方法,并调用super.setUp()
和super.tearDown()
。 然而,如果有人忘记叫超级或把它们放在错误的地方,抛出exception,并忘记在最后或者其他地方调用super,那么这可能会导致问题。
我想要做的是在基类final
的setUp
和tearDown
方法,然后添加我们自己的注释@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); } }