96

我有一个抽象基类,我将其用作单元测试的基础(TestNG 5.10)。在这个类中,我为我的测试初始化​​整个环境,设置数据库映射等。这个抽象类有一个带有@BeforeClass注释的方法来进行初始化。

接下来,我使用具有@Test方法和@BeforeClass方法的特定类扩展该类。这些方法对环境进行特定类的初始化(例如,将一些记录放入数据库)。

如何强制执行带@BeforeClass注释的方法的特定顺序?我需要在扩展类之前执行抽象基类中的那些。

例子:

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @BeforeClass
    doSpecificInitialization() {...}

    @Test
    doTests() {...}
}

预期顺序:

A.doInitialization
B.doSpecificInitialization
B.doTests

实际订单:

B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization        // <---not executed
 B.doTests)                // <-/
4

16 回答 16

119

编辑:下面的答案是针对JUnit的,但无论如何我都会把它留在这里,因为它可能会有所帮助。

根据JUnit api:“超类的 @BeforeClass 方法将在当前类之前运行。”

我对此进行了测试,它似乎对我有用。

但是,正如@Odys 在下面提到的,对于 JUnit,您需要将两个方法命名为不同的名称,否则将导致仅运行子类方法,因为父类将被隐藏。

于 2010-01-25T14:28:35.880 回答
53

不要把它@BeforeClass放在abstract课堂上。从每个子类中调用它。

abstract class A {
    void doInitialization() {}
}

class B extends A {
    @BeforeClass
    void doSpecificInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}

似乎 TestNG 有@BeforeClass(dependsOnMethods={"doInitialization"})- 试一试。

于 2010-01-25T14:19:36.987 回答
7

我添加public到抽象类和TestNG(6.0.1)之前执行了doInitialization()doTestsdoInitialization()如果我public从 A 类中删除, TestNG 不会执行。

public abstract class A {
 @BeforeClass
 doInitialization() {...}
}

class B extends A {    
 @Test
 doTests() {...}
}
于 2011-03-31T19:16:07.873 回答
6

我刚刚用 5.11 尝试了您的示例,并且首先调用了基类的 @BeforeClass。

您可以发布您的 testng.xml 文件吗?也许您在那里同时指定了 A 和 B,而只有 B 是必需的。

请随时跟进 testng-users 邮件列表,我们可以仔细查看您的问题。

——塞德里克

于 2010-01-26T00:16:15.177 回答
4

我刚刚经历了这一点,并找到了另一种实现这一目标的方法。只需在抽象类alwaysRun上使用@BeforeClass@BeforeMethod在抽象类中使用,即可按预期工作。

public class AbstractTestClass {
    @BeforeClass(alwaysRun = true)
    public void generalBeforeClass() {
        // do stuff
        specificBeforeClass();
    }
}
于 2013-12-04T08:33:21.853 回答
3

对于 JUnit:正如@fortega 所提到的:根据 JUnit api:“超类的 @BeforeClass 方法将在当前类之前运行。”

但注意不要用相同的名称命名这两个方法。因为在这种情况下,父方法将被子父隐藏。来源

于 2016-08-04T12:43:42.513 回答
2

当我运行时:JUnitCore.runClasses(TestClass.class); 它将在子级之前正确执行父级(您不需要super.SetUpBeforeClass();)如果您从 Eclipse 运行它:由于某种原因,它无法运行基类。解决方法:显式调用基类:( BaseTest.setUpBeforeClass(); ) 您可能希望在基类中有一个标志,以防您从应用程序运行它,以确定它是否已经设置。因此,如果您通过两种可能的方法运行它(例如从 eclipse 进行个人测试,以及通过 ANT 进行构建版本),它只会运行一次。

这似乎是 Eclipse 的一个错误,或者至少是意外的结果..

于 2011-11-17T20:56:14.593 回答
1

让您的 @BeforeClass 方法调用一个空的 specificBeforeClass() 方法,该方法可能会或可能不会被子类覆盖,如下所示:

public class AbstractTestClass {
  @BeforeClass
  public void generalBeforeClass() {
    // do stuff
    specificBeforeClass();
  }

  protected void specificBeforeClass() {}
}

public class SpecificTest {
  @Override
  protected void specificBeforeClass() {
    // Do specific stuff
  }

  // Tests
}
于 2010-07-09T11:41:22.007 回答
1

dependsOnMethod可以使用。

例如在 Spring ( AbstractTestNGSpringContextTests)的情况下

@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
于 2015-07-21T18:23:18.460 回答
1

检查您的导入声明。它应该是

import org.testng.annotations.BeforeClass;

不是

import org.junit.BeforeClass;

于 2018-02-03T04:36:34.210 回答
1

这对我有用——

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @Override
    @BeforeClass
    doInitialization() { 

       //do class specific init

    }   

    @Test
    doTests() {...}
}
于 2019-06-25T17:51:49.437 回答
0

为什么不尝试在超类中创建一个抽象方法 doSpecialInit(),从超类中的 BeforeClass 注释方法调用。

所以继承你的类的开发人员被迫实现这个方法。

于 2013-09-04T14:34:50.370 回答
0

这里还有另一个简单的解决方案。

我的特殊情况是,在执行超类中的“BeforeClass”之前,我需要从子类中的“BeforeClass”注入模拟服务。

为此 - 只需@ClassRule在子类中使用 a 。

例如:

@ClassRule
public static ExternalResource mocksInjector = new ExternalResource() {
    @Override
    protected void before() {
        // inject my mock services here
        // Note: this is executed before the parent class @BeforeClass
    }
};

我希望这有帮助。这可以有效地以“反向”顺序执行静态设置。

于 2017-03-22T09:47:54.830 回答
0

我今天遇到了类似的问题,唯一的区别是基类不是抽象的

这是我的情况

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    private void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}

发生了@BeforeClass从未执行过 A 类的方法。

  • A.doInitialization() -> 从来没有默默执行
  • B.doSpecificInitialization()
  • B.doTests()

使用隐私修饰符我发现如果方法从类继承者中不可见,TestNG将不会从继承的类中执行@BeforeClass注释的方法

所以这将起作用:

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    //Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors
    protected void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}

结果发生以下情况:

  • A.doInitialization()
  • B.doSpecificInitialization()
  • B.doTests()
于 2019-04-08T15:37:37.270 回答
-1

在我的情况下(JUnit),我在基类和派生类中有相同的方法,称为 setup()。在这种情况下,调用派生类的方法,而我让它调用基类方法。

于 2013-03-13T18:58:56.213 回答
-2

使用继承实现这一目标的更好和更清洁的方法可能如下 -

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

    @Override
    @BeforeClass
    void doInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}
于 2016-05-23T06:48:51.013 回答