简体   繁体   中英

Null pointer exception while trying to use one method in another class

I'm currently working on automating facebook login and logout, but I have problems. Basically, I have created a FacebookLogOutTest class, that needs to run FacebookLogIn first, and then continue. These are the classes:

FacebookLogIn

public class FacebookLogInTest {
    WebDriver driver;

    @Test
    public void facebookLogIn() {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        driver.get("https://www.facebook.com/");
        WebElement username = driver.findElement(By.id("email"));
        WebElement password = driver.findElement(By.id("pass"));
        WebElement login = driver.findElement(By.xpath("//*[@name='login']"));
        username.sendKeys("xxxxxx");
        password.sendKeys("xxxxxx");
        login.click();


    }
}
FabecookLogOut
public class FacebookLogOutTest {
    WebDriver driver;

    @Test
    public void facebookLogOut() {
        FacebookLogInTest fbLogin = new FacebookLogInTest();
        fbLogin.facebookLogIn();

        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        WebElement profileButton = driver.findElement(By.xpath(("//*[@aria-label='Your page']")));
        profileButton.click();
        WebElement logoutButton = driver.findElement(By.xpath("//span[text()='Log out']"));
        logoutButton.click();
    }
}

But when I'm trying to run the log out class, it throws an exception and I don't know why. The log in class works properly. What should I do?

Here's the stacktrace:

java.lang.NullPointerException
    at FacebookLogOutTest.facebookLogOut(FacebookLogOutTest.java:18)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

The problem is that you never assign a driver instance to the driver variable in facebookLogIn() . Each test should stand alone, eg you shouldn't be calling facebookLogIn() from facebookLogOut() . Each test should have it's own driver instance and should be run on it's own browser instance to keep your tests super clean.

Each test should look like this:

  1. Launch browser
  2. Do stuff
  3. Close browser

You have the right idea in trying to reuse code but investigate page objects instead. Create a page object for the login page (to log in) and one for the header (to click the profile icon and log out).

Now your test will look like:

WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.get("https://www.facebook.com/");

new HomePage(driver).logIn(username, password);

Header header = new Header(driver);
header.clickProfileIcon();
header.clickLogOut();

Very simple, very easy to read and lots of code reuse. Now when you create your second test, you can start with the same few lines of code setting up the driver and logging in and then get on to whatever the new test is supposed to cover.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM