Getting NullPointerException when trying to use FindElements to read all elements

51 Views Asked by At

I'm a beginner in using selenium-cucumber, I was trying to automate a web application i have the page objects where i used findelements to get all the elements that is where i'm getting the Null pointer exception

I was having similar issue before as well any leads on this is much appreciated

This is my first question let me know if any more info is required Feature file:

Feature: I want to select product on the page Scenario: Given user is on landing page When user enters username and password and click clickSignIn |username|[email protected]| |password|Hinata@12| And user hovers on the category and the product then selects required item |category|Women | |product |tops | |item |Hoodies & Sweatshirts| And user exists the browser.

Homepage class:

i have multiple options when i hover on them it will show more options to choose.

public HomePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }
public void productCategories(String category) {
        try {

            int size = optionsProduct.size();

            for (int i = 0; i < size; i++) {
                String actualText = optionsProduct.get(i).getText();
                String ExpectedText = category;

                if (actualText.equalsIgnoreCase(ExpectedText)) {
                    Actions actions = new Actions(driver);
                    WebElement categoryName = driver.findElement(By.xpath("//li[contains(@class,'level0')]/a/span[2]"));
                    actions.moveToElement(categoryName).perform();
                    System.out.println("===Moved to the Element"+ExpectedText);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

Step defs:

public class ProductTests {
    
    WebDriver driver;
    HomePage hp;
    
    
    
    @When("user hovers on the category and the product then selects required item")
    public void user_hovers_on_the_category_and_the_product_then_selects_required_item(DataTable dataTable) {
        hp = new HomePage(driver);
        Map<String, String> formdata = dataTable.asMap();
        String category = formdata.get("category");
        String product = formdata.get("product");
        String item = formdata.get("item");
        System.out.println("Category is"+category+"product is"+product+"item is"+item);
        
        hp.productCategories(category);
        hp.womensOptions(product);
        hp.womensSelection(item);
        
    }

}

Error: java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.SearchContext.findElements(org.openqa.selenium.By)" because "this.searchContext" is null

'Webdriver Instantiation:'

package driverLaunch;

import java.io.FileInputStream;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

import io.github.bonigarcia.wdm.WebDriverManager;

public class BasePage {

    WebDriver driver;
    Properties prop;

    public BasePage(WebDriver driver2) {
        this.driver = driver2;
    }

    public WebDriver init_driver(Properties prop) {
        String browser = prop.getProperty("browser");

        if (browser.equals("chrome")) {

            System.setProperty("webdriver.chrome.driver", "src/test/resources/Browser/chromedriver.exe");
            driver = new ChromeDriver();

        } else if (browser.equals("firefox")) {

            WebDriverManager.firefoxdriver().setup();
            driver = new FirefoxDriver();

        } else {
            System.out.println("Please provide a proper browser value..");
        }

        driver.manage().window().fullscreen();
        driver.manage().deleteAllCookies();
        driver.manage().window().maximize();
        driver.get(prop.getProperty("url"));

        return driver;
    }

    public Properties init_properties() {
        prop = new Properties();
        try {
            FileInputStream ip = new FileInputStream("src/test/resources/Config/config.properties");
            prop.load(ip);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return prop;

    }
}

Base Class:

@Given("user is on landing page")
public void user_is_on_landing_page() {
    
    bp = new BasePage(driver);
    Properties prop = bp.init_properties();
    driver = bp.init_driver(prop);
    
    //Click on SignIn
    hp = new HomePage(driver);
    hp.clickSignIn();
    
}
2

There are 2 best solutions below

3
Divyansh Gemini On

The NullPointerException is occurring because you are passing driver to the constructor of HomePage without initializing it.

Solution: Initialize driver before passing it to HomePage().

Updated Code:

public class ProductTests {
    WebDriver driver;
    HomePage hp;
    
    @When("user hovers on the category and the product then selects required item")
    public void user_hovers_on_the_category_and_the_product_then_selects_required_item(DataTable dataTable) {
        driver = new ChromeDriver();
        hp = new HomePage(driver);
        Map<String, String> formdata = dataTable.asMap();
        String category = formdata.get("category");
        String product = formdata.get("product");
        String item = formdata.get("item");
        System.out.println("Category is"+category+"product is"+product+"item is"+item);
        
        hp.productCategories(category);
        hp.womensOptions(product);
        hp.womensSelection(item);      
    }
}
0
M.P. Korstanje On

The design of your step definitions wasn't done right. Unlike JUnit where a single class with a @Test annotated method is instantiated for a test, when using Cucumber all classes with step definition annotations are instantiated for each test.

This also means you'll want to share state between steps, you can do this with cucmber-picocontainer. The tutorial is a bit old, but it works pretty much the same in io.cucumber as it did in info.cukes.

First add PicoContainer to your dependencies:

<dependencies>
  [...]
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-picocontainer</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
  [...]
</dependencies>

Then create a class to hold your webdriver and lazily instantiate it (this makes tests that don't use the webdriver faster).

public class WebDriverHolder implements Disposable {
    private WebDriver driver;

    public WebDriverHolder(){

    }

    public WebDriver getDriver() {
        if (driver != null) {
           return driver;
        }
        driver = // instantiate web driver here
        return driver; 
    }

    @Override
    public void dispose() {
        if (driver != null) {
           return;
        }
        driver. // shut down the driver here
    }

}

Then you inject the holder into other step definition classes and use it:

public class MyStepDefinitions {
    private final WebDriverHolder holder;
        
    public MyStepDefinitions(WebDriverHolder holder){
       this.holder = holder;
    }

    @Given("user is on landing page")
    public void user_is_on_landing_page() {
    
        WebDriver driver = holder.getDriver();

        // Do stuff with your driver, like creating the BasePage    
}


}