使用Appium+TestNG+BrowserStack时Page Object报空指针异常
问题:构造Page Object时抛出NullPointerException
在使用BrowserStack+Appium+TestNG编写自动化测试并引入Page Object模式时,构造页面对象时持续出现NullPointerException,报错行为LandingPage landingPage = new LandingPage(appiumDriver);
相关代码
BrowserStackConfig配置类
public class BrowserStackConfig { protected AppiumDriver<MobileElement> appiumDriver; @BeforeMethod(alwaysRun = true) @Parameters("platform") public void setUp(String platform, ITestResult testMethod) throws Exception { Map<String, Object> config = readConfigFromFile(); DesiredCapabilities capabilities = new DesiredCapabilities(); ConfigReader reader = new ConfigReader(); String device; String os; String app; switch (platform) { case "android": app = (String) config.get("androidApp"); device = (String) config.get("androidDevice"); os = (String) config.get("androidVersion"); break; case "ios": device = (String) config.get("iOSDevice"); os = (String) config.get("iOSVersion"); app = (String) config.get("iosApp"); break; default: throw new IllegalArgumentException("Unsupported OS: " + platform); } capabilities.setCapability("device", device); capabilities.setCapability("os_version", os); capabilities.setCapability("platformName", platform); capabilities.setCapability("app", app); capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60); capabilities.setCapability("idleTimeout", "1000"); capabilities.setCapability("settings[enableMultiWindows]", true); String url = reader.urlBrowserStack(testMethod); if ("android".equals(platform)) { appiumDriver = new AppiumDriver<>(new URL(url), capabilities); } else { appiumDriver = new IOSDriver<>(new URL(url), capabilities); } } private Map<String, Object> readConfigFromFile() throws IOException { Yaml yaml = new Yaml(); try (FileReader fileReader = new FileReader("browserstack.yml")) { return yaml.load(fileReader); } } @AfterMethod(alwaysRun = true) public void tearDown(ITestResult testResult) throws Exception { ResultsListener result = new ResultsListener(appiumDriver); if (ITestResult.SUCCESS == testResult.getStatus()) { result.passResult(appiumDriver); Thread.sleep(3000); } else { result.failResult(appiumDriver); Thread.sleep(3000); } appiumDriver.quit(); } }
BasePage基类
public class BasePage extends BrowserStackConfig{ protected AppiumDriver<MobileElement> appiumDriver; public BasePage (AppiumDriver<MobileElement> appiumDriver) { appiumDriver = this.appiumDriver; } }
LandingPage页面对象
public class LandingPage extends BasePage { public LandingPage(AppiumDriver<MobileElement> appiumDriver) { super(appiumDriver); } // Element locators private AndroidElement logInBtn = (AndroidElement ) new WebDriverWait(appiumDriver, 10).until( ExpectedConditions.visibilityOfElementLocated(MobileBy.id( "button_log_in" )) ); // Methods public boolean isInitialized() { try { return logInBtn.isDisplayed(); } catch (Exception e) { return false; } } }
AppTest测试类
public class AppTest extends BrowserStackConfig { private final SoftAssert assertion = new SoftAssert(); @Test public void test() throws Exception { LandingPage landingPage = new LandingPage(appiumDriver); // assert landing page is loaded assertion.assertTrue(landingPage.isInitialized()); } }
问题根源
- BasePage构造方法赋值颠倒:
appiumDriver = this.appiumDriver;将自身未初始化的null值覆盖传入的有效Driver实例,导致BasePage的成员变量appiumDriver始终为null。 - 元素初始化时机错误:LandingPage的
logInBtn在类实例化时直接初始化,此时appiumDriver还未被正确赋值,触发空指针。 - 冗余继承:BasePage继承BrowserStackConfig,测试类也继承该类,导致Driver实例管理混乱,增加空指针风险。
修复方案
1. 修正BasePage构造逻辑
移除不必要的继承,将传入的Driver正确赋值给成员变量:
public class BasePage { protected AppiumDriver<MobileElement> appiumDriver; public BasePage(AppiumDriver<MobileElement> appiumDriver) { this.appiumDriver = appiumDriver; } }
2. 延迟元素初始化(推荐使用PageFactory)
使用Appium的PageFactory来管理元素,避免在类加载时直接初始化:
public class LandingPage extends BasePage { public LandingPage(AppiumDriver<MobileElement> appiumDriver) { super(appiumDriver); // 初始化PageFactory元素 PageFactory.initElements(new AppiumFieldDecorator(appiumDriver), this); } @FindBy(id = "button_log_in") private AndroidElement logInBtn; public boolean isInitialized() { try { return new WebDriverWait(appiumDriver, 10) .until(ExpectedConditions.visibilityOf(logInBtn)) .isDisplayed(); } catch (Exception e) { return false; } } }
3. 验证Driver初始化有效性
在测试方法中添加日志或打印,确认@BeforeMethod是否成功初始化appiumDriver:
@Test public void test() throws Exception { System.out.println("Driver instance: " + appiumDriver); // 验证Driver是否为null LandingPage landingPage = new LandingPage(appiumDriver); assertion.assertTrue(landingPage.isInitialized()); assertion.assertAll(); }
内容的提问来源于stack exchange,提问作者peaches19219
相关产品推荐
相关产品推荐

