Are You Getting NullPointerException For Second TestNG Test While Running As A Suite?

Introduction

Let’s look at some queries asked by people online below.

When I am running my TestNG class individually then it is passing but when I run multiple TestNG classes together second TestNG class is failing with NullPointerException.

The value assigned to a variable in @BeforeSuite method is not reflecting properly in @Test methods

I encounter Null pointer exception when using @BeforeTest, @BeforeMethod and trying to run two classes from testng.xml

Hopefully, you must have got some idea of the problem defined in the above links. There is a common problem in all links just the way of explaining may be different. Beginners and experienced Selenium professionals both generally face this issue and end up creating static variables most of the time as a solution. If you have not understood the problem, do not worry. I will make you understand step by step.

Problem Explanation

First TestNG class

I have a common variable used in both @Test methods.

package SecondTestNullPointerException;

import org.testng.annotations.Test;

public class FirstTestNGClass {
	
	public String someVariable = "someValue";

	@Test
	public void firstMethodOfFirstTestNGClass()
	{
		System.out.println("Executing firstMethodOfFirstTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
	
	@Test
	public void secondMethodOfFirstTestNGClass()
	{
		System.out.println("Executing secondMethodOfFirstTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
}

Let’s run the above TestNG class.

Output
Executing firstMethodOfFirstTestNGClass...
Value of someVariable is : someValue
Executing secondMethodOfFirstTestNGClass...
Value of someVariable is : someValue

Expected output. Just to be more precise, both @Test methods were able to access the value of the common variable “someVariable”.

Let’s create another TestNG class as below:-

Second TestNG class

Like the first TestNG class above, This class also has a common variable used in both @Test methods.

package SecondTestNullPointerException;

import org.testng.annotations.Test;

public class SecondTestNGClass {
	
	public String someVariable = "someValue";

	@Test
	public void firstMethodOfSecondTestNGClass()
	{
		System.out.println("Executing firstMethodOfSecondTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
	
	@Test
	public void secondMethodOfSecondTestNGClass()
	{
		System.out.println("Executing secondMethodOfSecondTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
}
Output
Executing firstMethodOfSecondTestNGClass...
Value of someVariable is : someValue
Executing secondMethodOfSecondTestNGClass...
Value of someVariable is : someValue

Both First and Second TestNG classes have a similarity that they share a common variable “someVariable”. Let’s understand it in real-time practice with respect to selenium WebDriver scripts.

We require a browser to be launched for Selenium Scripts and launched browser to be closed at end of scripts. We may require some set up like establishing a database connection, an excel reader instance, any common variable, etc. One way is to have these stuff locally for each Test or class or use TestNG annotations to set it up once at suite or test or class level.

Let’s put the common variable “someVariable” under a TestNG annotation @BeforeSuite as we need the above variable to be initialized once and extend Setup class to both TestNG classes as below.

Setup class

package SecondTestNullPointerException;

import org.testng.annotations.BeforeSuite;

public class Setup {

	public String someVariable;

	@BeforeSuite
	public void setupVariable() {
		System.out.println("Executing setupVariable...");
		someVariable = "someValue";
	}

}

FirstTestNGClass

package SecondTestNullPointerException;

import org.testng.annotations.Test;

public class FirstTestNGClass extends Setup{
	
	@Test
	public void firstMethodOfFirstTestNGClass()
	{
		System.out.println("Executing firstMethodOfFirstTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
	
	@Test
	public void secondMethodOfFirstTestNGClass()
	{
		System.out.println("Executing secondMethodOfFirstTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
}

SecondTestNGClass

package SecondTestNullPointerException;

import org.testng.annotations.Test;

public class SecondTestNGClass extends Setup{
	
	@Test
	public void firstMethodOfSecondTestNGClass()
	{
		System.out.println("Executing firstMethodOfSecondTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
	
	@Test
	public void secondMethodOfSecondTestNGClass()
	{
		System.out.println("Executing secondMethodOfSecondTestNGClass...");
		System.out.println("Value of someVariable is : "+ someVariable);
	}
}

Let’s run both TestNG classes individually.

Output of FirstTestNGClass
Executing setupVariable...
Executing firstMethodOfFirstTestNGClass...
Value of someVariable is : someValue
Executing secondMethodOfFirstTestNGClass...
Value of someVariable is : someValue
Output of SecondTestNGClass
Executing setupVariable...
Executing firstMethodOfSecondTestNGClass...
Value of someVariable is : someValue
Executing secondMethodOfSecondTestNGClass...
Value of someVariable is : someValue

We can see how @BeforeSuite annotated method was called to initialize variable. Now let’s run both TestNG classes together using a TestNG xml.

SecondTestNullPointerException.xml




  
    
      
      
    
   
 
Output

Did you observe that for the second TestNG class you get the value of common variable “someVariable” as NULL? If you perform any action on this variable you will encounter NullPointerException.

As we know @BeforeSuite will be executed once and we are initializing common variables there. Each TestNG class extends class “Setup” which has @BeforeSuite method. But still, we are getting NULL value for the second test but not for the first test.

To understand the reason behind this behavior, you need to understand how does Inheritance works and TestNG annotations are grouped for execution.

We know that the class inherits the properties of another class using Inheritance. So in the above TestNG classes, “someVariable” is being inherited from Setup class and both TestNG classes have an individual instance of “someVariable”. TestNG groups annotations from all TestNG classes and run as per the mentioned annotation.

So in the above setup both TestNG classes have their own instance of Setup class. TestNG will club @BeforeSuite methods from both instances of Setup class as only one while running as a suite. So when @BeforeSuite method runs it initializes the common variable “someVariable” for first TestNG class which was consumed by @Test methods of First TestNG class. When the execution of the Second TestNG class begins, @BeforeSuite will not be executed again which results in the non-initialization of very own copy of variable “someVariable” in SecondTestNGClass and it remains NULL.

Understand with a flow diagram

Let’s try to understand the above concept using a diagram. Below is the initial setup we did. Class Setup is extended by both TestNG classes.

While running as a suite:-

You can see both TestNG class have their own instance of a class variable “someVariable” but the method which initializes that variable executed only once as per TestNG. There will not be any execution of @BeforeSuite method for the SecondTestNGClass separately and the inherited instance variable “someVariable” will not be initialized for SecondTestNGClass.

If you have multiple TestNG classes running together then only the first TestNG class will run fine and all other TestNG classes will fail with NullPointerException. I hope I am able to explain the actual problem and how generally we unwantedly do this and face NullPointerException.

We will see some solutions to this problem in other posts but the common solution to this problem is to change instance variables to class variables or static variables so that if it is initialized once it will be used by others (That is how a static variable works).

Setup class

package SecondTestNullPointerException;

import org.testng.annotations.BeforeSuite;

public class Setup {

	public static String someVariable;

	@BeforeSuite
	public void setupVariable() {
		System.out.println("Executing setupVariable...");
		someVariable = "someValue";
	}

}
Output
Executing setupVariable...
Executing firstMethodOfFirstTestNGClass...
Value of someVariable is : someValue
Executing secondMethodOfFirstTestNGClass...
Value of someVariable is : someValue
Executing firstMethodOfSecondTestNGClass...
Value of someVariable is : someValue
Executing secondMethodOfSecondTestNGClass...
Value of someVariable is : someValue

If you change instance variables to static variables, you should use it with ThreadLocal so that it will not create any problem while running in parallel.

You can download/clone the above sample project from here.

If you have any doubt, feel free to comment below.
If you like my posts, please like, comment, share and subscribe.
#ThanksForReading
#HappyLearning

Find all Selenium related posts here, all API manual and automation related posts here, and find frequently asked Java Programs here.

Many other topics you can navigate through the menu.

9 thoughts on “Are You Getting NullPointerException For Second TestNG Test While Running As A Suite?

  1. Hi Amod Mahajan,
    I facing similar Issue but in my case Second Testng class is skipped .I tried with changing Webdriver reference to Static .but no luck .My Setup is under @BeforeMethod and Closing Browser under @AfterMethod.Can you please help me to solve this issue

Leave a Reply

Your email address will not be published. Required fields are marked *