Appium长按操作抛出ClassCastException异常求助
解决Android自动化测试长按操作的ClassCastException异常
在Android自动化测试中,尝试对页面元素执行长按操作时,触发如下类型转换异常:
java.lang.ClassCastException: class jdk.proxy2.$Proxy15 cannot be cast to class org.openqa.selenium.remote.RemoteWebElement
相关代码
工具类代码
public class AndriodActions { AndroidDriver driver; public AndriodActions(AndroidDriver driver) { this.driver = driver; } public void longPressAction(WebElement element) { ((JavascriptExecutor) driver).executeScript("mobile: longClickGesture", ImmutableMap.of("elementId", ((RemoteWebElement) element), "duration", 5000)); } }
PO页面类代码
public class LoginPageLocators extends AndriodActions { AndroidDriver driver; public LoginPageLocators(AndroidDriver driver) { super(driver); this.driver = driver; PageFactory.initElements(driver, this); } @AndroidFindBy(xpath = "//android.view.View[@index='1']") private WebElement AppVersion; @AndroidFindBy(xpath = "//android.widget.EditText[@index='2']") private WebElement IPAdress; @AndroidFindBy(xpath = "//android.widget.Button[@content-desc='Save']") private WebElement SaveButton; @AndroidFindBy(xpath = "//android.widget.EditText[@text='Email']") private WebElement EmailAddress; @AndroidFindBy(xpath = "//android.widget.EditText[@text='Password']") private WebElement Password; @AndroidFindBy(xpath = "//android.widget.Button[@content-desc='SUBMIT']") private WebElement SubmitButton; public void setIpAddress(String address) { longPressAction(AppVersion); IPAdress.clear(); IPAdress.sendKeys(address); SaveButton.click(); } }
执行类代码
public class TestExecution extends BaseClass { @Test public void IpAddressSetup() throws Exception { String ipaddress = "https://facebook.com"; LoginPageLocators htmlElementLocators = new LoginPageLocators(driver); htmlElementLocators.setIpAddress(ipaddress); } }
完整报错信息
FAILED: IpAddressSetup java.lang.ClassCastException: class jdk.proxy2.$Proxy15 cannot be cast to class org.openqa.selenium.remote.RemoteWebElement (jdk.proxy2.$Proxy15 is in module jdk.proxy2 of loader 'app'; org.openqa.selenium.remote.RemoteWebElement is in unnamed module of loader 'app') at com.Utils.AndriodActions.longPressAction(AndriodActions.java:25) at com.Locators.LoginPageLocators.setIpAddress(LoginPageLocators.java:46) at com.testcases.TestExecution.IpAddressSetup(TestExecution.java:16) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133) at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:598) at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:173) at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46) at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:824) at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:146) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.testng.TestRunner.privateRun(TestRunner.java:794) at org.testng.TestRunner.run(TestRunner.java:596) at org.testng.SuiteRunner.runTest(SuiteRunner.java:377) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:371) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:332) at org.testng.SuiteRunner.run(SuiteRunner.java:276) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1212) at org.testng.TestNG.runSuitesLocally(TestNG.java:1134) at org.testng.TestNG.runSuites(TestNG.java:1063) at org.testng.TestNG.run(TestNG.java:1031) at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
解决方案
问题原因
PageFactory初始化的WebElement是动态代理对象(jdk.proxy2.$Proxy15),并非直接的RemoteWebElement实例,强制类型转换会触发ClassCastException。而mobile: longClickGesture脚本实际需要的是元素的ID,而非元素对象本身。
修改工具类的长按方法
将获取元素对象改为获取元素的ID,修改后的AndriodActions类代码如下:
import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebElement; import com.google.common.collect.ImmutableMap; import io.appium.java_client.android.AndroidDriver; import org.openqa.selenium.JavascriptExecutor; public class AndriodActions { AndroidDriver driver; public AndriodActions(AndroidDriver driver) { this.driver = driver; } public void longPressAction(WebElement element) { // 获取元素的ID,而非强制转换为RemoteWebElement String elementId = ((RemoteWebElement) element).getId(); ((JavascriptExecutor) driver).executeScript("mobile: longClickGesture", ImmutableMap.of("elementId", elementId, "duration", 5000)); } }
另一种可选方案(使用Appium的TouchAction)
如果上述方法仍有问题,也可以使用Appium原生的TouchAction类实现长按:
import io.appium.java_client.TouchAction; import io.appium.java_client.touch.LongPressOptions; import java.time.Duration; import org.openqa.selenium.WebElement; import io.appium.java_client.android.AndroidDriver; public class AndriodActions { AndroidDriver driver; public AndriodActions(AndroidDriver driver) { this.driver = driver; } public void longPressAction(WebElement element) { new TouchAction(driver) .longPress(LongPressOptions.longPressOptions() .withElement(element) .withDuration(Duration.ofSeconds(5))) .release() .perform(); } }
内容的提问来源于stack exchange,提问作者Baburaja Sabanayagam
相关产品推荐
相关产品推荐

