首页 > 解决方案 > java.lang.NullPointerException 正在生成

问题描述

为什么会发生以下情况,我如何在以下情况下使用它EnglishHomepage

我的代码(不工作):

public class EnglishHomepage {

    WebDriver driver = null; 

    public Actions action = new Actions(driver);

    By login_button = By.xpath("//*[@id=\"wrapper\"]/div[1]/header/div[2]/div[1]/div/a[15]");


    //constructor of EnglishHomepage
    public EnglishHomepage (WebDriver driver) {

        this.driver = driver; 
    }

    public void clickFogotPassword() {
        driver.findElement(login_button ).click();
    }


    public void clickDropdownValue() {

        action.doubleClick(driver.findElement(xpath2)).perform();   

    }
}

代码(工作)

public class EnglishHomepage {

    WebDriver driver = null; 

    By login_button = By.xpath("//*[@id=\"wrapper\"]/div[1]/header/div[2]/div[1]/div/a[15]");


    //constructor of EnglishHomepage
    public EnglishHomepage (WebDriver driver) {

        this.driver = driver; 
    }

    public void clickFogotPassword() {
        driver.findElement(login_button ).click();
    }


    public void clickDropdownValue() {

        **Actions action = new Actions(driver);**
        action.doubleClick(driver.findElement(xpath2)).perform();   

    }
}

我可以public Actions action = new Actions(driver);在该clickDropdownValue方法下使用,并且测试按预期工作正常。

然而,

当我public Actions action = new Actions(driver);在课堂下移动时,可以看到java.lang.NullPointerException

例外

在 java.util.Objects.requireNonNull(Objects.java:203) 在 org.openqa.selenium.interactions.Actions.(Actions.java:65) 在 pages.EnglishHomepage.(EnglishHomepage.java:12) 在 testcases.Tc4_Market_status。在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 处单击 (Tc4_Market_status.java:27)在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133) 在 org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:584 ) 在 org.testng.internal.MethodRunner 的 org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:172)。runInSequence(MethodRunner.java:46) at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:804) at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:145) at org.testng.internal .TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146) 在 org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128) 在 java.util.ArrayList.forEach(ArrayList.java:1257) 在 org.testng.TestRunner。 privateRun(TestRunner.java:770) at org.testng.TestRunner.run(TestRunner.java:591) at org.testng.SuiteRunner.runTest(SuiteRunner.java:402) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java :396) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:355) at org.testng.SuiteRunner.run(SuiteRunner.java:304) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1180) at org.testng.TestNG.runSuitesLocally(TestNG.java:1102) at org.testng.TestNG.runSuites(TestNG.java:1032) 在 org.testng.TestNG.run(TestNG.java:1000) 在 org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) 在 org.testng .remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) 在 org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)

标签: javaselenium

解决方案


如果new Actions(driver)位于构造函数之上,则在构造函数体之前执行,即 的值driver仍然为空。

如果new Actions(driver)位于构造函数的下方,则在构造函数体之后执行,即 的值driver将是传递给构造函数的值。

建议:在字段初始化器中,永远不要使用在自己的初始化器中未完全初始化的另一个字段,也永远不要使用稍后声明的字段。

正确的方法是在构造函数中初始化字段,其中值可用。

WebDriver driver; // No need to initialize to null, it's the default

public Actions action; // Don't initialize here

public EnglishHomepage (WebDriver driver) {
    this.driver = driver; 
    this.action = new Actions(driver);
}

更新

实际上,根据 Java 语言规范第12.5节,向下移动字段声明不应该奏效。新类实例的创建,它指定了这个初始化顺序(释义):

分配内存并调用构造函数,其评估如下:

  • 如果此构造函数以 开头this(...),则调用另一个构造函数。使用这些相同的步骤递归地处理该构造函数调用。

  • 否则,调用超类构造函数,或者使用super(...)语句指定,或者隐式调用无参数超类构造函数。

  • 执行该类的实例初始化程序实例变量初始化程序,将实例变量初始化程序的值分配给相应的实例变量,按照它们在源代码中以文本形式出现的从左到右的顺序。

  • 执行此构造函数的其余部分。

可以看出,根据规范,构造函数主体(除了this(...)and )总是最后执行,因此将字段声明向下移动到构造函数下方不应该改变字段在初始化字段时super(...)的事实。drivernullaction

上面给出的建议是要走的路。


推荐阅读