@BeforeClass and inheritance - execution order

I have a base base class that I use as the basis for my unit tests (TestNG 5.10). In this class, I initialize the entire environment for my tests by setting up database mappings, etc. This abstract class has a method with @BeforeClass annotation that performs initialization.

Then I extend this class with specific classes in which I have @Test methods as well as @BeforeClass methods. These methods initialize the class-specific environment (for example, put some records in the database).

How can I enforce a certain order of annotated @BeforeClass methods? I need those from an abstract base class that must be executed before those propagated in the class.

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) // <-/ 
+82
java unit-testing testng
Jan 25
source share
16 answers

Do not put @BeforeClass in the abstract class. Call it from each subclass.

 abstract class A { void doInitialization() {} } class B extends A { @BeforeClass void doSpecificInitialization() { super.doInitialization(); } @Test void doTests() {} } 

TestNG seems to have @BeforeClass(dependsOnMethods={"doInitialization"}) - try it.

+39
Jan 25 '10 at 14:19
source share

edit: The answer below is for JUnit , but I will leave it here anyway, because it might be useful.

According to the JUnit api : "The @BeforeClass methods of superclasses will be executed before those that belong to the current class."

I tested this and it seems to work for me.

However, as @Odys mentions below, for JUnit you need to have two methods differently , but, as otherwise, only the subclass method will be executed, because the parent will be obscured.

+94
Jan 25
source share

I added public to the abstract class, and TestNG (6.0.1) did doInitialization () before doTests . TestNG does not do doInitialization() if I remove public from class A.

 public abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Test doTests() {...} } 
+7
Mar. 31 '11 at 19:16
source share

I just tried your example with 5.11, and I first call @BeforeClass from the base class.

Can you place the testng.xml file? Perhaps you specify both A and B there, while only B is required.

Feel free to follow the testng-users mailing list and we can take a closer look at your issue.

- Cedric

+6
Jan 26 '10 at 0:16
source share

I just went through this and found another way to achieve this. Just use alwaysRun in @BeforeClass or @BeforeMethod in an abstract class, as you would expect.

 public class AbstractTestClass { @BeforeClass(alwaysRun = true) public void generalBeforeClass() { // do stuff specificBeforeClass(); } } 
+3
Dec 04 '13 at 8:33
source share

When I run from: JUnitCore.runClasses (TestClass.class); It will correctly perform parental controls in front of the child (you do not need super.SetUpBeforeClass (); ). If you run it from Eclipse: For some reason, it cannot run the base class. Work around: Call the base class explicitly: ( BaseTest.setUpBeforeClass (); ) You might want to have a flag in the base class if you run it from the application to determine whether it is already configured or not. Therefore, it runs only once if you run it using both of the possible methods (for example, from eclipse for personal testing and through ANT to release the assembly).

This seems to be a bug with Eclipse, or at least unexpected results.

+2
Nov 17 '11 at 20:56
source share

For JUnit : As @fortega said: According to the JUnit api: "The @BeforeClass methods of superclasses will execute to those that belong to the current class."

But be careful not to call both methods with the same name . Since in this case the parent method will be hidden by the child parent. Source

+2
Aug 04 '16 at 12:43 on
source share

How about getting your @BeforeClass method to call the empty specificBeforeClass () method, which may or may not be overwritten by similar subclasses:

 public class AbstractTestClass { @BeforeClass public void generalBeforeClass() { // do stuff specificBeforeClass(); } protected void specificBeforeClass() {} } public class SpecificTest { @Override protected void specificBeforeClass() { // Do specific stuff } // Tests } 
+1
Jul 09 '10 at
source share

dependsOnMethod .

eg. in case of Spring ( AbstractTestNGSpringContextTests )

 @BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance") 
+1
Jul 21 '15 at 18:23
source share

Check your expression for import. That is how it should be

import org.testng.annotations.BeforeClass;

not

import org.junit.BeforeClass;

+1
Feb 03 '18 at 4:36
source share

Why don't you try to create the abstract doSpecialInit () method in your superclass called from the annotated BeforeClass method in the superclass.

Thus, developers who inherit your class are forced to implement this method.

0
Sep 04 '13 at 14:34
source share

Here is another simple solution.

My special situation is that I need to inject layouts with "BeforeClass" into a subclass before "BeforeClass" is executed in the superclass.

To do this, simply use @ClassRule in a 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 } }; 

Hope this helps. This can effectively perform static configuration in reverse order.

0
Mar 22 '17 at 9:47 on
source share

I ran into a similar problem today, the only difference was that the base class was not

Here is my case

 public class A { @BeforeClass private void doInitialization() {...} } public class B extends A { @BeforeClass private void doSpecificInitialization() {...} @Test public void doTests() {...} } 

@BeforeClass method from class A has never been executed.

  • A.doInitialization () β†’ IT WAS NEVER FULFILLED
  • B.doSpecificInitialization ()
  • B.doTests ()

When playing with privacy modifiers, I found that TestNG will not execute the annotated @BeforeClass method from the inherited class if the method is not visible from the @BeforeClass class

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, the following occurs:

  • A.doInitialization ()
  • B.doSpecificInitialization ()
  • B.doTests ()
0
Apr 08 '19 at 15:37
source share

It works for me -

 abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Override @BeforeClass doInitialization() { //do class specific init } @Test doTests() {...} } 
0
Jun 25 '19 at 17:51
source share

In my case (JUnit), I have the same methods as setup () in the base class and the derived class. In this case, only the method of the derived class is called, and I call the method of the base class.

-one
Mar 13 '13 at 18:58
source share

The best and cleaner way to achieve this through inheritance might be the following:

 abstract class A { @BeforeClass void doInitialization() {} } class B extends A { @Override @BeforeClass void doInitialization() { super.doInitialization(); } @Test void doTests() {} } 
-2
May 23 '16 at 6:48
source share



All Articles