When migrating from JUnit4 to JUnit5 I found a change in the behaviour of JUnit4 and JUnit5 and wanted to check if the change was a bug in JUnit4 or in JUnit5 and how to do it correctly.
Lets assume the following structure:
One base class
public class BaseTestClass {
#Before
public void setUp(){
System.out.println("Base Test Class");
}
}
Another class that inherits from this base class
public class InheritsFromBase extends BaseTestClass {
#Override
public void setUp() {
System.out.println("I inherit from base");
super.setUp();
}
}
And an actual test class
public class ActualTests extends InheritsFromBase {
#Test
public void myTest(){
Assert.assertTrue(true);
}
}
If I run myTest() in JUnit 4 then the setUp() method of both, BaseTestClass and InheritsFromBase is called.
After migrating this code to JUnit5, the setUp() methods are not called anymore. I had to manually add the #BeforeEach annotation on InheritsFromBase.
Resulting in the following classes:
public class BaseTestClass {
#BeforeEach
public void setUp(){
System.out.println("Base Test Class");
}
}
public class InheritsFromBase extends BaseTestClass {
#Override
#BeforeEach
public void setUp() {
System.out.println("I inherit from base");
super.setUp();
}
}
public class ActualTests extends InheritsFromBase {
#Test
public void myTest(){
Assertions.assertTrue(true);
}
}
So my question: Was the behaviour in JUnit4 correct or in JUnit5?
The actual behavior for JUnit 5 is expected as the #BeforeEach javadoc states :
Inheritance
#BeforeEach methods are inherited from superclasses as long as they
are not overridden.
You override the setup() method that contains #BeforeEach in the InheritsFromBase class.
So it is not inherited any longer.
For JUnit 4, the #Before javadoc doesn't state any particularity and inheritance abilities.
So you should consider the actual behavior as "normal" but no documented.
To get the same behavior with JUnit 5, you should do the reverse what you do with JUni4 : remove #BeforeEach in the super class and add it only in the subclass.
public class BaseTestClass {
public void setUp() {
System.out.println("Base Test Class");
}
}
public class InheritsFromBase extends BaseTestClass {
#Override
#BeforeEach
public void setUp() {
System.out.println("I inherit from base");
super.setUp();
}
}
As I execute the tests, it produces as output :
I inherit from base
Base Test Class
Related
I have multiple testNG test classes that extend a Base Test class and all use the same common objects. I want to have the object creation done automatically in BaseTest so I don't have to include it in each test class. As of now, the code only works if I add createPages() to the start of the test. I tried putting them in the BaseTest class using #BeforeClass and #BeforeSuite but both gave a null pointer exception meaning they weren't instantiated before the #Test test123 was run I beleive.
public someTest extends BaseTest {
#Test
public void test123(){
createPages(); //i want to be able to remove this and have it done in BaseTest
menuPage.scroll();
}
}
public BaseTest {
MenuPage menuPage;
public void createPages() {
menuPage = new MenuPage(getDriver());
}
/*
#BeforeSuite
public void beforeSuite() {
createPages();
}
#BeforeClass
public void beforeClass() {
createPages();
}
*/
}
#beforeTest is one such annotation. A method with #beforeTest annotation will run, before any test method belonging to the classes inside the test tag
inside ur BaseTest
public class Basetest{
#BeforeTest
public void doBeforeTest() {
createPages();
}
}
How can I execute a method once before all tests in all classes start?
I have a program that needs a system property to be set before any test start. Is there any way to do that?
Note: #BeforeClass or #Before are used just for the same test class. In my case, I'm looking for a way to execute a method before all test classes start.
To setup precondition to your test cases you can use something like this -
#Before
public void setUp(){
// Set up you preconditions here
// This piece of code will be executed before any of the test case execute
}
if you need to run that method before the start of all test you should use the annotation #BeforeClass or if you need to execute the same method every time you will execute a test method of that class you must use #Before
f.e
#Before
public void executedBeforeEach() {
//this method will execute before every single test
}
#Test
public void EmptyCollection() {
assertTrue(testList.isEmpty());
}
You can make use of a Test Suite.
The test suite
#RunWith(Suite.class)
#Suite.SuiteClasses({ TestClass.class, Test2Class.class, })
public class TestSuite {
#BeforeClass
public static void setup() {
// the setup
}
}
and, the test classes
public class Test2Class {
#Test
public void test2() {
// some test
}
}
public class TestClass {
#Test
public void test() {
// some test
}
}
Or, you can have a base class which handles the setup
public class TestBase {
#BeforeClass
public static void setup() {
// setup
}
}
and, then the test classes can extend the base class
public class TestClass extends TestBase {
#Test
public void test() {
// some test
}
}
public class Test2Class extends TestBase {
#Test
public void test() {
// some test
}
}
However, this will call the setup method in TestBase for all its subclasses everytime each of them executes.
I am writing automation testing script for a project . Here , I will have many test classes for which I will be using same #BeforeTest Method . I tried by creating a base class (in which I declared before test method ) and extending them in my test classes . But its not working . Is there any other way to have a common beforeTest method in a seperate java file and use it for all my test classes .
Using a base class for my other classes works for me. You should use #BeforeMethod for your needs since #BeforeTest is used to run any #Test included in the <test> tag in a testNG.xml file.
public class BaseClass {
#BeforeMethod
public void before() {
System.out.println("Before method");
}
}
and then
public class ATestClass extends BaseClass {
#Test
public void testOne() {
System.out.println("testOne run");
}
#Test
public void testTwo() {
System.out.println("testTwo run");
}
}
gave me the result
Try it out!
If you are using PowerMockito or Mockito you can achieve by following.
public abstract class ParentClass{
#Before
public void init() {
System.out.println("inniinii");
}
}
#RunWith(PowerMockRunner.class)
public class ChildClass extends ParentClass{
#Test
public void test() {
System.out.println("hello test");
}
}
I have a little problem with testNG. Below my example code:
abstract class parent {
abstract void beforeTest();
#Test
void test() {
// some testing
}
}
class child extends parent {
#BeforeTest
void beforeTest() {
\\some before things
}
}
And the question is how to do this code work properly? So I want to perform beforeTest() method and if it fails the test method shoud skip. How can I achieve this thing?
Usually, the configuration methods go into the parrent and test classes should extend the parrent.
So, try using this example for your tests:
abstract class TestBase {
#BeforeTest
public void beforeTest() {
// do config here
// this will run for each of you <test> tag in your testng.xml suite
}
#BeforeMethod
public void beforeMethod() {
// do some config here
// this will run for each method annotated with #Test
}
}
class SomeTestClass extends TestBase {
#Test
public void some_test() {
// some testing
}
}
I'm trying to create a Junit test suite along with using PowerMockRunner but it does not work.
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(MainTest.class)
#Suite.SuiteClasses({ MainTest.Class1Test.class })
#PrepareForTest({
StaticFieldsProvider.class
})
public class MainTest extends Suite {
public MainTest(Class<?> klass, RunnerBuilder builder)
throws InitializationError {
super(klass, builder);
}
public static class TestBase {
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(StaticFieldsProvider.class);
}
}
public static class Class1Test extends TestBase {
#Before
public void setUp() {
super.setUp();
}
#Test
public void test(){
assertTrue(true);
}
}
}
When I try to run, it fails with error -
java.lang.IllegalArgumentException: Test class can only have one constructor
at org.junit.runners.model.TestClass.(TestClass.java:40)
Any suggestions on how to use PowerMockRunner in above case?
Thanks
This is an old question, so we may get no resolution on whether or not this solution works for the OP; but this might work (I can't verify without having access to StaticFieldsProvider, but it works if I swap that out with one of my own classes). I would love for someone to edit and add more explanation as to why this works:
#RunWith(PowerMockRunner.class)
// * Delegate to Suite.class instead of MainTest.class *
#PowerMockRunnerDelegate(Suite.class)
#Suite.SuiteClasses({ MainTest.Class1Test.class })
#PrepareForTest({
StaticFieldsProvider.class
})
// * Don't extend Suite *
public class MainTest {
// * Remove constructor *
public static class TestBase {
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(StaticFieldsProvider.class);
}
}
public static class Class1Test extends TestBase {
#Before
public void setUp() {
super.setUp();
}
#Test
public void test(){
assertTrue(true);
}
}
}
In case it helps someone else, I had a slightly different scenario in that only a couple of the classes in my suite need PowerMockRunner (and don't mock out the same thing, so the mock needs to happen in each individual test class instead of in the runner). It appears that as long as I #PrepareForTest in my runner (as above) the classes I will need in some of the test classes, I can still create the mocks in the #Before (or wherever) of the applicable test class. Hope this helps.
You must not extend Suite, because this is a part of JUnit 3 and you are using JUnit 4. (Remove the extends and the constructor.) See the JUnit Wiki for more datails about Suites in JUnit 4.