我有一个抽象基类,我将其用作单元测试的基础(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) // <-/
答案 0 :(得分:93)
编辑:下面的答案适用于 JUnit ,但无论如何我都会留在这里,因为它可能会有所帮助。
根据JUnit api:“超类的@BeforeClass方法将在当前类之前运行。”
我测试了这个,它似乎对我有用。
但是,正如@Odys在下面提到的那样,对于JUnit,您需要使用两个名称不同的方法,否则将导致仅运行子类方法,因为父项将被镜像。 / p>
答案 1 :(得分:38)
不要将@BeforeClass
放在abstract
课程上。从每个子类中调用它。
abstract class A {
void doInitialization() {}
}
class B extends A {
@BeforeClass
void doSpecificInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
看起来像TestNG有@BeforeClass(dependsOnMethods={"doInitialization"})
- 尝试一下。
答案 2 :(得分:7)
我将public
添加到抽象类,TestNG(6.0.1)在doTests
之前执行了doInitialization()。如果我从A类中删除doInitialization()
,则TestNG不会执行public
。
public abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Test
doTests() {...}
}
答案 3 :(得分:6)
我刚用5.11尝试了你的例子,我首先调用了基类的@BeforeClass。
你可以发布你的testng.xml文件吗?也许你在那里同时指定A和B,而只需要B。
随时关注testng-users邮件列表,我们可以仔细查看您的问题。
- 塞德里克
答案 4 :(得分:3)
我刚刚经历过这个,并找到了另一种方法来实现这一目标。只需在摘要类中的alwaysRun
或@BeforeClass
上使用@BeforeMethod
,就可以正常工作。
public class AbstractTestClass {
@BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
答案 5 :(得分:2)
当我从以下地方开始运行时: JUnitCore.runClasses(TestClass.class); 它将在子项之前正确执行父项(您不需要 super.SetUpBeforeClass(); ) 如果从Eclipse运行它: 由于某种原因,它无法运行基类。 解决方法: 明确地调用基类:( BaseTest.setUpBeforeClass(); ) 您可能希望在基类中有一个标志,以防您从应用程序运行它,以确定它是否已经设置。因此,如果您通过两种可能的方法运行它(例如从eclipse进行个人测试,通过ANT进行构建发布),它只会运行一次。
这似乎是Eclipse的一个错误,或者至少是意外的结果..
答案 6 :(得分:2)
对于JUnit : 正如@fortega所说: 根据JUnit api:&#34;超类的@BeforeClass方法将在当前类之前运行。&#34;
但请注意不要将两个方法命名为同名。因为在这种情况下,父方法将隐藏父方法。 Source
答案 7 :(得分: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
}
答案 8 :(得分:1)
dependsOnMethod
可以使用。
e.g。如果是春天(AbstractTestNGSpringContextTests
)
@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
答案 9 :(得分:1)
检查您的import语句。 它应该是
import org.testng.annotations.BeforeClass;
不是
import org.junit.BeforeClass;
答案 10 :(得分:0)
为什么不尝试在超类中创建一个抽象方法doSpecialInit(),从超类中的BeforeClass注释方法调用。
所以继承你的类的开发者被迫实现这个方法。
答案 11 :(得分:0)
这里有另一个简单的解决方案。
我的特殊情况是我需要从&#34; BeforeClass&#34;中注入模拟服务。在&#34; BeforeClass&#34;之前的子类中在超类中执行。
要做到这一点 - 只需在子类中使用@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
}
};
我希望这会有所帮助。这可以在&#34;反向&#34;中有效地执行静态设置。顺序。
答案 12 :(得分:0)
我今天也遇到了类似的问题,唯一的区别是基类不是抽象的
这是我的情况
public class A {
@BeforeClass
private void doInitialization() {...}
}
public class B extends A {
@BeforeClass
private void doSpecificInitialization() {...}
@Test
public void doTests() {...}
}
发生了从未执行过类A的@BeforeClass
方法。
在使用隐私修饰符时,我发现如果从类继承程序中看不到方法,则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() {...}
}
结果发生以下情况:
答案 13 :(得分:0)
这对我有用-
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Override
@BeforeClass
doInitialization() {
//do class specific init
}
@Test
doTests() {...}
}
答案 14 :(得分:-1)
在我的情况下(JUnit)我在基类和派生类中使用了相同的方法setup()。在这种情况下仅调用派生类的方法,并让它调用基类方法。
答案 15 :(得分:-2)
使用继承实现此目的的更好,更清晰的方法可能如下 -
abstract class A {
@BeforeClass
void doInitialization() {}
}
class B extends A {
@Override
@BeforeClass
void doInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}