@BeforeClass和inheritance – 执行顺序

我有一个抽象的基类,作为我的unit testing(TestNG 5.10)的基础。 在这个类中,我为我的testing初始化​​了整个环境,设置了数据库映射等等。这个抽象类有一个带有@BeforeClass注解的方法来完成初始化。

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

我怎样才能强制@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) // <-/ 

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

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

看起来像TestNG有@BeforeClass(dependsOnMethods={"doInitialization"}) – 试试看。

编辑:下面的答案是JUnit ,但是我会把它留在这里,因为它可能是有帮助的。

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

我testing了这个,它似乎为我工作。

但是,正如@Odys在下面提到的那样,对于JUnit,你需要有两个不同名字方法 ,否则会导致只运行子类方法,因为父类会被映射。

我只是用5.11来试用你的例子,并且首先调用基类的@BeforeClass。

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

请随时关注testng用户邮件列表,我们可以仔细研究您的问题。

– 塞德里克

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

 public abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Test doTests() {...} } 

我刚刚经历了这一点,并find了一个更好的方法来实现这一目标。 只需在抽象类的@BeforeClass@BeforeMethod上使用alwaysRun ,就可以像您期望的那样工作。

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

如何让你的@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 } 

当我运行: JUnitCore.runClasses(TestClass.class); 它会在孩子之前正确地执行父代(你不需要super.SetUpBeforeClass(); )如果你从Eclipse运行它:出于某种原因,它无法运行基类。 解决方法:明确地调用基类:( BaseTest.setUpBeforeClass(); )如果从应用程序运行基类,您可能希望在基类中有一个标志,以确定它是否已经安装。 所以它只运行一次,如果你通过两种可能的方法来运行它(例如从eclipse进行个人testing,并通过ANT进行构build发布)。

这似乎是与Eclipse的错误,或至less意想不到的结果..

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

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

dependsOnMethod可以使用。

例如在Spring的情况下( AbstractTestNGSpringContextTests

 @BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance") 

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

所以inheritance你的类的开发者被迫实现这个方法。

这里有另一个简单的解决scheme。

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

要做到这一点 – 只需在子类中使用@ClassRule

例如:

 @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 } }; 

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

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

一个更好,更干净的方式来实现这个使用inheritance可能如下 –

 abstract class A { @BeforeClass void doInitialization() {} } class B extends A { @Override @BeforeClass void doInitialization() { super.doInitialization(); } @Test void doTests() {} }