@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() {} }