Junit @Before/@After 的调用顺序是什么?
我有一个集成测试套件。我有一个 IntegrationTestBase
类供我的所有测试扩展。该基类有一个 @Before
(public void setUp()
) 和 @After
(public void TeaDown()
) >) 建立API和DB连接的方法。我一直在做的只是在每个测试用例中重写这两个方法并调用 super.setUp() 和 super.tearDown() 。然而,如果有人忘记调用 super 或将它们放在错误的位置并抛出异常并且他们忘记在finally 中调用 super 或其他东西,这可能会导致问题。
我想要做的是在基类 final
上创建 setUp
和 tearDown
方法,然后添加我们自己的带注释的 @Before
和 @After
方法。进行一些初始测试时,它似乎总是按此顺序调用:
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?* }
}
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 setUp()
) and @After
(public void tearDown()
) method to establish API and DB connections. What I've been doing is just overriding those two methods in each testcase and calling super.setUp()
and super.tearDown()
. However this can cause problems if someone forgets to call the super or puts them at the wrong place and an exception is thrown and they forget to call super in the finally or something.
What I want to do is make the setUp
and tearDown
methods on the base class final
and then just add our own annotated @Before
and @After
methods. Doing some initial tests it appears to always call in this order:
Base @Before
Test @Before
Test
Test @After
Base @After
but I'm just a little concerned that the order isn't guaranteed and that it could cause problems. I looked around and haven't seen anything on the subject. Does anyone know if I can do that and not have any problems?
Code:
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?* }
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,这种行为是有保证的:
@Before
< /a>:@After
:Yes, this behaviour is guaranteed:
@Before
:@After
:以前困扰过我的一个潜在问题:
我喜欢在每个测试类中最多有一个
@Before
方法,因为运行类中定义的@Before
方法的顺序不保证。通常,我会调用这样的方法setUpTest()
。但是,尽管
@Before
被记录为超类的 @Before 方法将在当前类的方法之前运行。没有定义其他顺序。
,仅当用@Before
标记的每个方法在类层次结构中具有唯一的名称时才适用。例如,我有以下内容:
我期望
AbstractFooTest.setUpTest()
在FooTest.setUpTest()
之前运行,但只有FooTest.setupTest()
代码> 已执行。AbstractFooTest.setUpTest()
根本没有被调用。代码必须修改如下才能工作:
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 methodsetUpTest()
.But, although
@Before
is documented asThe @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:
I expected
AbstractFooTest.setUpTest()
to run beforeFooTest.setUpTest()
, but onlyFooTest.setupTest()
was executed.AbstractFooTest.setUpTest()
was not called at all.The code must be modified as follows to work:
我认为根据
@Before
和@After
的文档,正确的结论是为方法赋予唯一的名称。我在测试中使用以下模式:并
给出结果
这种方法的优点:
AbstractBaseTest
类的用户无法覆盖setUp
/tearDown
偶然的方法。如果他们愿意,他们需要知道确切的名字并且可以做到。这种方法的(小)缺点:用户无法看到在
setUp
/tearDown
之前或之后发生的事情。他们需要知道这些东西是由抽象类提供的。但我认为这就是他们使用抽象类的原因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:and
give as a result
Advantage of this approach: Users of the
AbstractBaseTest
class cannot override thesetUp
/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如果你扭转局面,你可以声明你的基类抽象,并让后代声明在基类带注释的setUp和tearDown方法中调用的setUp和tearDown方法(不带注释)。
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.
您可以使用
@BeforeClass
注释来确保setup()
始终首先被调用。同样,您可以使用@AfterClass注释来确保总是最后调用tearDown()。通常不建议这样做,但支持。
这并不完全是您想要的 - 但它本质上会在测试运行的整个过程中保持数据库连接打开,然后在最后一劳永逸地关闭它。
You can use
@BeforeClass
annotation to assure thatsetup()
is always called first. Similarly, you can use@AfterClass
annotation to assure thattearDown()
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.
这不是对标语问题的答案,而是对问题正文中提到的问题的答案。不要使用 @Before 或 @After,而是考虑使用 @org.junit.Rule 因为它给你更多的灵活性。 ExternalResource(从 4.7 开始)是您最感兴趣的规则如果您正在管理连接。另外,如果您希望保证规则的执行顺序,请使用 RuleChain (自 4.10 起)。我相信当提出这个问题时所有这些都是可用的。下面的代码示例是从ExternalResource 的javadocs 复制的。
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.