Java @BeforeClass 和继承 - 执行顺序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2132734/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@BeforeClass and inheritance - order of execution
提问by Dominik Sandjaja
I have an abstract base class, which I use as a base for my unit tests (TestNG 5.10). In this class, I initialize the whole environment for my tests, setting up database mappings, etc. This abstract class has a method with a @BeforeClass
annotation which does the initialization.
我有一个抽象基类,我将其用作单元测试 (TestNG 5.10) 的基础。在这个类中,我为我的测试初始化整个环境,设置数据库映射等。这个抽象类有一个带有@BeforeClass
注释的方法,用于初始化。
Next, I extend that class with specific classes in which I have @Test
methods and also @BeforeClass
methods. These methods do class-specific initialization of the environment (e.g. put some records into the database).
接下来,我使用具有@Test
方法和@BeforeClass
方法的特定类扩展该类。这些方法执行特定于类的环境初始化(例如,将一些记录放入数据库)。
How I can enforce a specific order of the @BeforeClass
annotated methods? I need the ones from the abstract base class to be executed before the ones of the extending class.
如何强制执行带@BeforeClass
注释的方法的特定顺序?我需要在扩展类之前执行抽象基类中的那些。
Example:
例子:
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@BeforeClass
doSpecificInitialization() {...}
@Test
doTests() {...}
}
Expected order:
预期顺序:
A.doInitialization
B.doSpecificInitialization
B.doTests
Actual order:
实际订单:
B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization // <---not executed
B.doTests) // <-/
采纳答案by Bozho
Don't put the @BeforeClass
on the abstract
class. Call it from each subclass.
不要把它@BeforeClass
放在abstract
课堂上。从每个子类调用它。
abstract class A {
void doInitialization() {}
}
class B extends A {
@BeforeClass
void doSpecificInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
Seems like TestNG has @BeforeClass(dependsOnMethods={"doInitialization"})
- give it a try.
似乎 TestNG 有@BeforeClass(dependsOnMethods={"doInitialization"})
- 试一试。
回答by Fortega
edit:Answer below is for JUnit, but I will leave it here anyway, because it could be helpful.
编辑:下面的答案是针对JUnit 的,但无论如何我都会把它留在这里,因为它可能会有所帮助。
According to the JUnit api: "The @BeforeClass methods of superclasses will be run before those the current class."
根据JUnit api:“超类的 @BeforeClass 方法将在当前类之前运行。”
I tested this, and it seems to work for me.
我对此进行了测试,它似乎对我有用。
However, as @Odys mentions below, for JUnit you need to have the two methods named differentlythough as doing otherwise will result in only the subclass method being run because the parent will be shadowed.
但是,正如@Odys 在下面提到的,对于 JUnit,您需要对两个方法进行不同的命名,否则只会导致运行子类方法,因为父类将被隐藏。
回答by Cedric Beust
I just tried your example with 5.11 and I get the @BeforeClass of the base class invoked first.
我刚刚在 5.11 中尝试了您的示例,并且首先调用了基类的 @BeforeClass。
Can you post your testng.xml file? Maybe you are specifying both A and B there, while only B is necessary.
你能发布你的 testng.xml 文件吗?也许你在那里指定了 A 和 B,而只有 B 是必要的。
Feel free to follow up on the testng-users mailing-list and we can take a closer look at your problem.
请随时关注 testng-users 邮件列表,我们可以仔细查看您的问题。
-- Cedric
——塞德里克
回答by Tatome
How about having your @BeforeClass method call an empty specificBeforeClass() method that may or may not be overwritten by sub classes like so:
让您的 @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
}
回答by Paul
I added public
to the abstract class and TestNG (6.0.1) executed the doInitialization() before doTests
. TestNG does not execute doInitialization()
if I remove public
from class A.
我添加public
到抽象类和 TestNG (6.0.1) 之前执行了 doInitialization() doTests
。doInitialization()
如果我public
从 A 类中删除,TestNG 不会执行。
public abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Test
doTests() {...}
}
回答by Steve
When I run from: JUnitCore.runClasses(TestClass.class);It will execute the parent properly, before the child (You do not need super.SetUpBeforeClass();) If you run it from Eclipse: For some reason it fails to run the base class. The work around: Call the base class explicitely: (BaseTest.setUpBeforeClass();) You may want to have a flag in the base class in case you run it from an application, to determine if it is already setup or not. So it only runs once if you run it via both possible methods (such as from eclipse for personal testing, and through ANT for a build release).
当我运行时:JUnitCore.runClasses(TestClass.class); 它将在子级之前正确执行父级(您不需要super.SetUpBeforeClass();)如果您从 Eclipse 运行它:由于某种原因,它无法运行基类。解决方法:显式调用基类:( BaseTest.setUpBeforeClass();) 您可能希望在基类中有一个标志,以防您从应用程序运行它,以确定它是否已经设置。因此,如果您通过两种可能的方法运行它,它只会运行一次(例如从 eclipse 进行个人测试,通过 ANT 进行构建版本)。
This appears to be a bug with Eclipse, or at least unexpected results..
这似乎是 Eclipse 的一个错误,或者至少是意外的结果。
回答by Mike Sokolov
In my case (JUnit) I have the same methods called setup() in the base class and the derived class. In this case onlythe derived class's method is called, and I have it call the base class method.
就我而言(JUnit),我在基类和派生类中有相同的方法,称为 setup()。在这种情况下,只调用派生类的方法,我让它调用基类方法。
回答by Ludo
Why don't you try to create an abstract method doSpecialInit() in your super class, called from your BeforeClass annotated method in superclass.
为什么不尝试在超类中创建一个抽象方法 doSpecialInit(),从超类中的 BeforeClass 注释方法调用。
So developpers inheriting your class is forced to implement this method.
因此,继承您的类的开发人员被迫实现此方法。
回答by Konrad Garus
I've just gone through this and found one more way to achieve this. Just use alwaysRun
on @BeforeClass
or @BeforeMethod
in the abstract class, works as you would expect.
我刚刚经历了这个并找到了另一种方法来实现这一目标。只需在抽象类alwaysRun
上@BeforeClass
或@BeforeMethod
在抽象类中使用,就可以按您的预期工作。
public class AbstractTestClass {
@BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
回答by Sandeep Jindal
dependsOnMethod
can be used.
dependsOnMethod
可以使用。
e.g. in case of Spring (AbstractTestNGSpringContextTests
)
例如在 Spring ( AbstractTestNGSpringContextTests
) 的情况下
@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")