@BeforeClass 및 상속-실행 순서
단위 테스트 (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) // <-/
수업 @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 메소드는 현재 클래스보다 먼저 실행됩니다."
나는 이것을 테스트했고 그것은 나를 위해 작동하는 것 같습니다.
그러나 @Odys가 아래에서 언급했듯이 JUnit의 경우 두 메서드의 이름을 다르게 지정 해야합니다. 그렇지 않으면 부모가 섀도 잉되므로 하위 클래스 메서드 만 실행됩니다.
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 abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Test
doTests() {...}
}
I just tried your example with 5.11 and I get the @BeforeClass of the base class invoked first.
Can you post your testng.xml file? Maybe you are specifying both A and B there, while only B is necessary.
Feel free to follow up on the testng-users mailing-list and we can take a closer look at your problem.
-- Cedric
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.
public class AbstractTestClass {
@BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
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).
This appears to be a bug with Eclipse, or at least unexpected results..
For JUnit: As @fortega has mentioned: According to the JUnit api: "The @BeforeClass methods of superclasses will be run before those the current class."
But be careful not to name both methods with the same name. Since in this case the parent method will be hidden by child parent. Source.
How about having your @BeforeClass method call an empty specificBeforeClass() method that may or may not be overwritten by sub classes like so:
public class AbstractTestClass {
@BeforeClass
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
protected void specificBeforeClass() {}
}
public class SpecificTest {
@Override
protected void specificBeforeClass() {
// Do specific stuff
}
// Tests
}
dependsOnMethod
can be used.
e.g. in case of Spring (AbstractTestNGSpringContextTests
)
@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
Check your import statement. It should be
import org.testng.annotations.BeforeClass;
not
import org.junit.BeforeClass;
Why don't you try to create an abstract method doSpecialInit() in your super class, called from your BeforeClass annotated method in superclass.
So developpers inheriting your class is forced to implement this method.
There is another easy solution here.
My particular situation is that I need to inject mock services from "BeforeClass" in the subclass before "BeforeClass" in the superclass is executed.
To do this - simply use a @ClassRule
in the subclass.
For example:
@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
}
};
I hope this helps. This can effectively execute static setup in "reverse" order.
I've faced a similar issue today, the only difference was a Base class was not abstract
Here's my case
public class A {
@BeforeClass
private void doInitialization() {...}
}
public class B extends A {
@BeforeClass
private void doSpecificInitialization() {...}
@Test
public void doTests() {...}
}
It occurred that a @BeforeClass
method from class A was never executed.
- A.doInitialization() -> THIS WAS NEVER EXECUTED silently
- B.doSpecificInitialization()
- B.doTests()
Playing with privacy modifiers I found that TestNG will not execute a @BeforeClass
annotated method from inherited class if a method is not visible from a class-inheritor
So this will work:
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() {...}
}
As a result following happens:
- A.doInitialization()
- B.doSpecificInitialization()
- B.doTests()
This works for me --
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Override
@BeforeClass
doInitialization() {
//do class specific init
}
@Test
doTests() {...}
}
In my case (JUnit) I have the same methods called setup() in the base class and the derived class. In this case only the derived class's method is called, and I have it call the base class method.
A better and cleaner way to achieve this using inheritance may be as following -
abstract class A {
@BeforeClass
void doInitialization() {}
}
class B extends A {
@Override
@BeforeClass
void doInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
참고URL : https://stackoverflow.com/questions/2132734/beforeclass-and-inheritance-order-of-execution
'developer tip' 카테고리의 다른 글
유형이 내부 유형을 사용하므로 속성을 public으로 선언 할 수 없습니다. (0) | 2020.09.14 |
---|---|
Java의 Enum final에 compareTo가있는 이유는 무엇입니까? (0) | 2020.09.14 |
window.location.href와 top.location.href의 차이점 (0) | 2020.09.14 |
숫자의 정수 및 소수 부분을 얻는 방법? (0) | 2020.09.13 |
글꼴 멋진 아이콘을 정적으로 회전 (0) | 2020.09.13 |