Junit @ Before/@之后的命令是什么?

Joe*_*oel 128 java installation junit teardown

我有一个集成测试套件.我有一个IntegrationTestBase课程,我的所有测试都要扩展.此基类具有@Before(public void setUp())和@After(public void tearDown())方法来建立API和DB连接.我一直在做的就是在每个测试用例中调用这两个方法并调用super.setUp()super.tearDown().但是,如果有人忘记调用父类或者把它们放在错误的地方,并抛出一个异常,他们会忘记在最后什么超级调用此可能会出现问题.

我想要做的是在基类上创建setUptearDown方法final,然后添加我们自己的注释@Before@After方法.做一些初始测试似乎总是按此顺序调用:

Base @Before
Test @Before
Test
Test @After
Base @After
Run Code Online (Sandbox Code Playgroud)

但我只是担心订单无法保证并且可能会导致问题.我环顾四周,没有看到任何关于这个问题的内容.有谁知道我能做到这一点而没有任何问题吗?

码:

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?* }
}
Run Code Online (Sandbox Code Playgroud)

axt*_*avt 129

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

@Before:

@Before超类的方法将在当前类的方法之前运行,除非它们在当前类中被重写.没有定义其他排序.

@After:

@After在超类中声明的方法将在当前类的方法之后运行,除非它们在当前类中被重写.

  • 需要说明的是,并不保证所有`@ Before`方法的执行顺序.如果有10个`@ Before`方法,则每个方法都可以按任意顺序执行; 就在任何其他方法之前. (15认同)
  • 请参阅John Q Citizen所述的重要文章:"这仅适用于标有@Before的每个方法在类层次结构中都有唯一名称的情况"非常重要,请记住! (5认同)
  • 因此,您可以用自己的语言解释一下,而不是引用有些含糊不清的文档吗?`@ Before`和`@ After`方法是在每个*其他类方法(每个方法一次)之前运行,还是在整个类方法之前和之后运行(每个类一次)? (4认同)

Joh*_*zen 49

以前咬过我的一个潜在问题:

我希望@Before每个测试类中最多只有一个方法,因为@Before不保证运行类中定义的方法的顺序.通常,我会称这种方法setUpTest().

但是,虽然@Before记录为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() { 
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我期望AbstractFooTest.setUpTest()之前运行FooTest.setUpTest(),但只是FooTest.setupTest()被执行了.AbstractFooTest.setUpTest()根本没被召唤.

必须按如下方式修改代码才能工作:

public void FooTest extends AbstractFooTest {
  @Before
  public void setUpTest() {
    super.setUpTest();
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 只是为了让事情变得更安全:为避免名称冲突,您可以在基类`final`中创建`@ Before` /`@ After`方法,因此如果您(不小心)尝试将编译器抱怨在子类中覆盖它们. (22认同)
  • 未运行同名的父方法听起来不像JUnit行为.这听起来像OOP中的基本覆盖是如何工作的.父方法在运行时基本上不存在.孩子将其替换为所有意图和目的.这就是Java的工作原理. (4认同)

Mat*_*fel 20

我认为基于文档@Before@After正确的结论是给方法唯一的名称.我在测试中使用以下模式:

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");
  }
}
Run Code Online (Sandbox Code Playgroud)

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");
  }
}
Run Code Online (Sandbox Code Playgroud)

给出结果

AbstractBaseTest.setUp
Test.setUp
test1
Test.tearDown
AbstractBaseTest.tearDown
AbstractBaseTest.setUp
Test.setUp
test2
Test.tearDown
AbstractBaseTest.tearDown
Run Code Online (Sandbox Code Playgroud)

此方法的优点:AbstractBaseTest类的用户无法意外地覆盖setUp/tearDown方法.如果他们愿意,他们需要知道确切的名字并且可以做到.

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

  • 很好的例子 - 如果你有两个@Test方法会更加说明,所以可以看出setUp和tearDown wrap*each*test方法. (2认同)