使用 Guice @Inject 时未初始化 @FindBy WebElements

@FindBy WebElements not initialized when using Guice @Inject

我目前在正确实施对象注入方面遇到了一些问题。我正在使用页面对象模型编写一些 Cucumber 测试。我在以下代码中得到 NullPointerExceptions:

public class BasePage extends LoadableComponent<BasePage>{
    @Inject
    protected WebDriver driver  //trying to inject a WebDriver instance here

    public BasePage(){
        PageFactory.initElements(this.driver, this);    
    }
    @Override
    protected void isLoaded() throws Error {//something here}
    @Override
    protected void load() {//something as well}

    // some more shared methods   
}

上面是我的 BasePage class,LoginPage extends BasePage 如下

public class LoginPage extends BasePage {
    @FindBy(id="login_username")
    private WebElement userNameField;
    @FindBy(id="login_password")
    private WebElement passWordField;
    @FindBy(id="login_database")
    private WebElement dataBase;

    public void enterValidLoginCredentials() throws FileNotFoundException {
        userNameField.sendKeys(EdgeTestProperties.getProperty("userName"));
        passWordField.sendKeys(EdgeTestProperties.getProperty("password"));
        dataBase.sendKeys(EdgeTestProperties.getProperty("db"));
    }        

    //some more tests here        

}

我的步骤定义登录测试:

@ScenarioScoped
public class LoginSteps {

    private LoginPage login;

    @Inject
    LoginSteps(LoginPage login) {
    this.login = login;
    }

    @Given("^I'm on the login page$")
        public void getLoginPage() throws FileNotFoundException {
        login.get();    
    }

    @When("^I enter valid user credential")
    public void enterValidUserCredential() throws FileNotFoundException {
        login.enterValidLoginCredentials();
    }

在我的 CucumberModule 中,我使用了:

public class CucumberModule extends AbstractModule {
    @Override
    protected void configure() {
        requestStaticInjection(BasePage.class);     
    }

    @Provides
    @ScenarioScoped
    WebDriver getWebDriver(){
        WebDriver driver = null;

        try {
            driver =  Browser.loadDriver(EdgeTestProperties.getProperty("browser"));
        } catch (FileNotFoundException e) {
            System.err.print("Failed to load the browser preference, check test properties file....");
            e.printStackTrace();
        }
        driver.manage().timeouts().implicitlyWait(2L, TimeUnit.SECONDS);    

        return driver;
    }
}

当我开始 运行 登录测试时,BasePage 上的驱动程序的 @Injection 仅在调用基本构造函数之后发生( WebElement 的初始化秒)。结果, WebElement 中的 none 被初始化,所以我得到 NullPointerException。如果我删除超级 class 构造函数并将驱动程序注入点更改为 LoginPage 构造函数并通过设置驱动程序和初始化 WebElements,但这似乎是错误的。有没有更好的办法?

你应该使用构造函数注入。

这将解决您的问题,因为驱动程序现在可以在构造函数中使用。

protected final Webdriver driver;

@Inject
public BasePage(WebDriver driver) {
    this.driver = driver;
    PageFactory.initElements(this.driver, this);
}

你应该知道,一般来说,字段注入不是首选。你发现了一个原因;另一个原因是它 hard to test. 构造函数注入更冗长,但它也使阅读代码和尝试编写测试时发生的事情更加清晰。