Java @BeforeClass和继承-执行顺序
我有一个抽象基类,用作单元测试的基础(TestNG 5.10)。在这个类中,我为我的测试初始化了整个环境,设置了数据库映射等。这个抽象类有一个带有Java @BeforeClass和继承-执行顺序,java,unit-testing,testng,Java,Unit Testing,Testng,我有一个抽象基类,用作单元测试的基础(TestNG 5.10)。在这个类中,我为我的测试初始化了整个环境,设置了数据库映射等。这个抽象类有一个带有@BeforeClass注释的方法来进行初始化 接下来,我用特定的类扩展该类,在这些类中我有@Test方法和@BeforeClass方法。这些方法执行特定于类的环境初始化(例如,将一些记录放入数据库) 如何强制执行带注释方法的@BeforeClass的特定顺序?我需要先执行抽象基类中的,然后执行扩展类中的 例如: abstract class A {
@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) // <-/
B.doSpecificationInitialization/不要将@BeforeClass
放在抽象类上。从每个子类调用它
abstract class A {
void doInitialization() {}
}
class B extends A {
@BeforeClass
void doSpecificInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
似乎TestNG已经-尝试一下。编辑:下面的答案是针对JUnit的,但我还是把它留在这里,因为它可能会有所帮助
根据:“超类的@BeforeClass方法将在当前类的方法之前运行。”
我测试了这个,它似乎对我有效
然而,正如@Odys在下面提到的,对于JUnit,您需要以不同的方式命名两个方法,尽管这样做只会导致运行子类方法,因为父类将被隐藏。我刚刚用5.11尝试了您的示例,我首先调用了基类的@BeforeClass
您可以发布testng.xml文件吗?可能您在那里同时指定了A和B,而只有B是必需的
请随时关注testng用户邮件列表,我们可以更仔细地查看您的问题
--
Cedric让@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
}
我向抽象类添加了public
,TestNG(6.0.1)在doTests
之前执行doInitialization()。如果我从类A中删除public
,TestNG不会执行doInitialization()
public abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Test
doTests() {...}
}
当我从运行时:JUnitCore.runClasses(TestClass.class)强>
它将在子级之前正确执行父级(您不需要super.SetUpBeforeClass();)
如果从Eclipse运行它:
由于某种原因,它无法运行基类。
解决办法:
明确地调用基类:(BaseTest.setUpBeforeClass();)
如果从应用程序运行基类,您可能希望在基类中有一个标志,以确定它是否已经设置好。因此,如果您通过这两种可能的方法运行它,那么它只运行一次(例如从eclipse进行个人测试,通过ANT进行构建版本)
这似乎是Eclipse的一个bug,或者至少是意外的结果。在我的例子(JUnit)中,基类和派生类中有相同的方法setup()。在这种情况下,只调用派生类的方法,我让它调用基类方法 为什么不尝试在超类中创建一个抽象方法doSpecialInit(),从超类中的BeforeClass注释方法调用它呢
因此继承您的类的开发人员被迫实现这个方法。我刚刚讨论了这个问题,并找到了另一种实现方法。只需在抽象类中的@BeforeClass
或@beforethod
上使用alwaysRun
,即可正常工作
public class AbstractTestClass {
@BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
可以使用dependsOnMethod
e、 g.如果是弹簧(AbstractTestNGSpringContextTests
)
使用继承实现此目的的更好、更干净的方法可能如下所示-
abstract class A {
@BeforeClass
void doInitialization() {}
}
class B extends A {
@Override
@BeforeClass
void doInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
对于JUnit:
正如@fortega所提到的:
根据JUnitAPI:“超类的@BeforeClass方法将在当前类的方法之前运行。”
但是要小心,不要用相同的名称命名这两个方法。因为在这种情况下,父方法将被子-父方法隐藏 这里还有另一个简单的解决方案
我的特殊情况是,我需要在执行超类中的“BeforeClass”之前,从子类中的“BeforeClass”注入模拟服务
为此,只需在子类中使用@ClassRule
abstract class A {
void doInitialization() {}
}
class B extends A {
@BeforeClass
void doSpecificInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
例如:
@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
}
};
我希望这有帮助。这可以有效地以“反向”顺序执行静态设置。检查导入语句。
应该是
import org.testng.annotations.BeforeClass代码>
不是
import org.junit.BeforeClass代码>我今天遇到了类似的问题,唯一的区别是基类不是抽象的
这是我的箱子
public class A {
@BeforeClass
private void doInitialization() {...}
}
public class B extends A {
@BeforeClass
private void doSpecificInitialization() {...}
@Test
public void doTests() {...}
}
类a中的@BeforeClass
方法从未执行过
- A.doInitialization()->此操作从未以静默方式执行
- B.剂量规格初始化()
- 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.初步化()
- B.剂量规格初始化()
- B.doTests()
这对我很有用--
这基本上就是我想要避免的:不需要显式调用超级(抽象)类的方法。特别是我还有一些类,它们继承自一个,但没有自己的@BeforeClass方法。我只需要插入一个就可以了。
dependsOnMethods
解决方法解决了这个问题。虽然我更喜欢“超类优先”的方法……但使用“dependsOnMethod”时,“doInitialization”不应该用“@Test”来表示吗?我
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Override
@BeforeClass
doInitialization() {
//do class specific init
}
@Test
doTests() {...}
}