You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Selenium/Appium时出现Session ID is null错误,求解决方法

问题排查:Session ID is null. Using WebDriver after calling quit()?

错误信息

org.openqa.selenium.WebDriverException: org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?
Build info: version: '4.8.2', revision: '826dbfc730'
System info: os.name: 'Mac OS X', os.arch: 'aarch64', os.version: '13.2.1', java.version: '1.8.0_362'
Driver info: io.appium.java_client.android.AndroidDriver
Command: [null, findElement {using=xpath, value=//*[@text='Enter PIN']}]
Capabilities {appium:app: /Users/chandan/Desktop/mobi..., appium:appActivity: com.comviva.mobiquityconsum..., appium:appPackage: com.comviva.mobiquity.consu..., appium:autoGrantPermissions: true, appium:automationName: UiAutomator2, appium:clearDeviceLogsOnStart: true, appium:databaseEnabled: false, appium:desired: {app: /Users/chandan/Desktop/mobi..., appium:appActivity: com.comviva.mobiquityconsum..., appium:appPackage: com.comviva.mobiquity.consu..., autoGrantPermissions: true, automationName: UiAutomator2, clearDeviceLogsOnStart: true, deviceName: Pixel5, eventTimings: true, ignoreHiddenApiPolicyError: true, newCommandTimeout: 30000, noReset: false, platformName: android, platformVersion: 12, udid: emulator-5554}, appium:deviceApiLevel: 31, appium:deviceManufacturer: Google, appium:deviceModel: sdk_gphone64_arm64, appium:deviceName: emulator-5554, appium:deviceScreenDensity: 440, appium:deviceScreenSize: 1080x2340, appium:deviceUDID: emulator-5554, appium:eventTimings: true, appium:ignoreHiddenApiPolicyError: true, appium:javascriptEnabled: true, appium:locationContextEnabled: false, appium:networkConnectionEnabled: true, appium:newCommandTimeout: 30000, appium:noReset: false, appium:pixelRatio: 2.75, appium:platformVersion: 12, appium:statBarHeight: 145, appium:takesScreenshot: true, appium:udid: emulator-5554, appium:viewportRect: {height: 1927, left: 0, top: 145, width: 1080}, appium:warnings: {}, appium:webStorageEnabled: false, platformName: ANDROID}

测试类代码

@AfterMethod
public void tearDown(){
    DriverFactory.quitDriver();
}

@BeforeMethod
public void startDriver(){
    DriverFactory.getMobileAppDriver();
}

@Test(priority = 1)
public void  InvalidLogin(){
    ExtentManager.startTestFromProperty(pNode, TestCases.getTestCase("SMOKE_TC_07"));
    startPositveTest();
    login.login(DataDriven.getUserByStatus("Y"),"1234");
}

@Test(priority = 2)
public  void  ElectricBill(){
    ExtentManager.startTestFromProperty(pNode, TestCases.getTestCase("SMOKE_TC_02"));
    startPositveTest();
    login.enterPin(DataDriven.getUserPinByStatus("Y"));
    billPay.electricityBillPay("50","OD23432123",DataDriven.getUserPinByStatus("Y"));
}

Driver Factory代码

public class DriverFactory {

    private static WebDriver driver;
    private static AppiumDriver mobileDriver;
    private static final Logger logger = LoggerFactory.getLogger(DriverFactory.class);

    public static AppiumDriver getMobileAppDriver(){
       try{
           if(mobileDriver != null){
               return mobileDriver;
           }

           if (MobileProperties.getProperty("device.platform").equalsIgnoreCase("android")) {
               mobileDriver = MobileDriver.getAndroidDriver();
               logger.info("Info :  ");
           }
           else {
               mobileDriver = MobileDriver.getIOSDriver();
           }
       }
        catch (Exception e){
           e.printStackTrace();
        }
        return mobileDriver;
    }

    public static void quitDriver() {
        if (mobileDriver == null) {
            return;
        }
        mobileDriver.quit();
        mobileDriver = null;
    }
}

问题原因

  • 测试类中startDriver()仅调用getMobileAppDriver()但未将新创建的driver实例传递给login、billPay等页面对象,导致这些页面对象持有已被销毁的旧driver引用(第一个测试用例执行完tearDown()后,driver被quit并置为null,但页面对象仍保留之前的引用)。
  • 页面对象(如LoginPage、BillPayPage)若为静态实例或初始化时绑定了固定driver,未在每次测试前更新引用,就会在第二个测试用例执行时使用已失效的driver发起操作,触发NoSuchSessionException。

解决办法

1. 测试类中更新页面对象的driver引用

修改@BeforeMethod方法,获取新driver实例后,重新初始化页面对象:

@BeforeMethod
public void startDriver(){
    AppiumDriver driver = DriverFactory.getMobileAppDriver();
    // 每次测试前重新初始化页面对象,传入最新的driver
    login = new LoginPage(driver);
    billPay = new BillPayPage(driver);
}

2. 页面对象采用实例化传参模式

确保页面对象不持有静态driver,而是在构造时传入driver实例,操作时使用该实例:

public class LoginPage {
    private final AppiumDriver driver;

    // 构造方法传入driver
    public LoginPage(AppiumDriver driver) {
        this.driver = driver;
    }

    public void enterPin(String pin) {
        // 使用当前实例的driver执行操作
        driver.findElement(By.xpath("//*[@text='Enter PIN']")).sendKeys(pin);
    }
}

3. 增加日志验证执行流程

在DriverFactory中添加日志,确认driver的创建和销毁流程是否符合预期:

public static AppiumDriver getMobileAppDriver(){
    try{
        if(mobileDriver != null){
            logger.info("返回已存在的移动端Driver实例");
            return mobileDriver;
        }
        logger.info("创建新的移动端Driver实例");
        if (MobileProperties.getProperty("device.platform").equalsIgnoreCase("android")) {
            mobileDriver = MobileDriver.getAndroidDriver();
        }
        else {
            mobileDriver = MobileDriver.getIOSDriver();
        }
    } catch (Exception e){
        logger.error("创建移动端Driver失败", e);
        e.printStackTrace();
    }
    return mobileDriver;
}

public static void quitDriver() {
    if (mobileDriver == null) {
        logger.info("移动端Driver已为null,跳过销毁操作");
        return;
    }
    logger.info("销毁移动端Driver实例");
    mobileDriver.quit();
    mobileDriver = null;
}

4. 验证测试方法执行顺序

确认测试框架(如TestNG)的@BeforeMethod和@AfterMethod是否在每个测试用例前后正确执行,确保每个测试用例都使用独立的driver实例。


内容的提问来源于stack exchange,提问作者Chandan Dash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:25:00