【问题标题】:NPE when constructor is being called调用构造函数时的 NPE
【发布时间】:2014-10-07 21:38:22
【问题描述】:

我有以下java类(实现页面对象模式)

package core.pageObjects;

import org.openqa.selenium.*;

public class ConsultaClientePorDocumento {

    private WebDriver driver;

    public ConsultaClientePorDocumento(WebDriver d){
        this.driver = d;
    }

    public WebElement cancelarButton = driver.findElement(By.id("Cancelar"));
}

然后我尝试像这样在我的测试中使用它:

import core.pageObjects.*;

ConsultaClientePorDocumento consultaCPD = new ConsultaClientePorDocumento(driver);

我收到以下错误:

java.lang.NullPointerException
at core.pageObjects.ConsultaClientePorDocumento.<init>(ConsultaClientePorDocumento.java:16)

我做错了什么?

【问题讨论】:

    标签: java selenium pageobjects


    【解决方案1】:

    在构造函数的主体之前初始化字段(对超类构造函数的任何显式或隐式调用除外)。这意味着当cancelarButton 被初始化时,driver 还没有被构造函数初始化;它仍然具有null 的默认值。

    在初始化driver 之后将cancelarButton 初始化代码放在构造函数中,以确保在cancelarButton 的初始化代码中需要driver 之前对其进行初始化。

    private WebDriver driver;
    
    public ConsultaClientePorDocumento(WebDriver d){
        this.driver = d;
        this.cancelarButton = driver.findElement(By.id("Cancelar"));
    }
    
    public WebElement cancelarButton;
    

    JLS, Section 12.5,指定此行为:

    就在对新创建对象的引用作为结果返回之前,使用以下过程处理指示的构造函数以初始化新对象:

    1. 将构造函数的参数分配给此构造函数调用新创建的参数变量。

    2. 如果此构造函数以同一类中另一个构造函数的显式构造函数调用(第 8.8.7.1 节)开始(使用 this),则评估参数并使用这五个相同的步骤递归地处理该构造函数调用。如果该构造函数调用突然完成,则此过程出于相同原因而突然完成;否则,继续第 5 步。

    3. 此构造函数不是以显式调用同一类中的另一个构造函数开始的(使用 this)。如果此构造函数用于 Object 以外的类,则此构造函数将以显式或隐式调用超类构造函数开始(使用 super)。使用这五个相同的步骤递归地评估超类构造函数调用的参数和过程。如果该构造函数调用突然完成,则此过程出于相同的原因突然完成。否则,继续第 4 步。

    4. 执行该类的实例初始化程序和实例变量初始化程序,将实例变量初始化程序的值分配给相应的实例变量,按照它们在源代码中以文本形式出现的从左到右的顺序。如果执行这些初始化程序中的任何一个导致异常,则不会处理更多初始化程序,并且此过程会突然完成相同的异常。否则,继续第 5 步。

    5. 执行此构造函数的其余部分。如果该执行突然完成,则此过程出于同样的原因突然完成。否则,此过程正常完成。

    我已经强调了最后一步,即执行构造函数的其余部分。

    【讨论】:

    • 我明白了,谢谢!问题是页面的每个 WebElement 都应该在测试需要它们时进行初始化,而不是在页面构造器阶段。所以我想我需要某种方法来在调用元素时初始化 WebElement。像这样: public WebElement cancelarButton(){ WebElement cancelarButton = driver.findElement(By.id("id"); return cancelarButton }
    【解决方案2】:

    您正在尝试在构造函数设置之前使用driver。将cancelarButton的初始化移到构造函数中:

    public ConsultaClientePorDocumento(WebDriver d){
        this.driver = d;
        cancelarButton = driver.findElement(By.id("Cancelar"));
    }
    
    public WebElement cancelarButton;
    

    字段在文件中的位置无关紧要,它们都将在调用构造函数之前进行评估。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 2018-05-30
      • 2014-07-15
      • 2015-09-10
      • 1970-01-01
      • 2011-04-16
      相关资源
      最近更新 更多