How to fix java.lang.ClassCastException.
Overview
In this tutorial, we will fix a Selenium test that fails with the exception java.lang.ClassCastException: class org.openqa.selenium.By$ByCssSelector cannot be cast to class org.openqa.selenium.WebElement.
Error Trace
java.lang.ClassCastException: class org.openqa.selenium.By$ByCssSelector cannot be cast to class org.openqa.selenium.WebElement (org.openqa.selenium.By$ByCssSelector and org.openqa.selenium.WebElement are in unnamed module of loader 'app') at com.testingdocs.sample.AppTest.firstTest(AppTest.java:16) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0( Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke( NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke( DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.testng.internal.MethodInvocationHelper.invokeMethod( MethodInvocationHelper.java:134) at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:597) 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:816) 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:1510) at org.testng.TestRunner.privateRun(TestRunner.java:766) at org.testng.TestRunner.run(TestRunner.java:587) at org.testng.SuiteRunner.runTest(SuiteRunner.java:384) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337) at org.testng.SuiteRunner.run(SuiteRunner.java:286) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1187) at org.testng.TestNG.runSuitesLocally(TestNG.java:1109) at org.testng.TestNG.runSuites(TestNG.java:1039) at org.testng.TestNG.run(TestNG.java:1007) at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66) at com.intellij.rt.testng.RemoteTestNGStarter.main( RemoteTestNGStarter.java:110)
Buggy Code
package com.testingdocs.sample; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.Test; public class AppTest { @Test public void firstTest() { WebDriver driver = new FirefoxDriver(); try { driver.get("http://localhost"); WebElement result = (WebElement)By.cssSelector("div.page_header"); Assert.assertEquals(result.getText(),"Apache2 Ubuntu Default Page"); } finally { driver.quit(); } } }
Fix
We can take the clue from the exception trace on which line you get the exception. If you figure out the error it’s ok. In many cases, we may need to debug the test to find the actual cause of the exception.
WebElement result = (WebElement)By.cssSelector("div.page_header");
Many automation engineers just try to typecast the locating finding technique to the class of the WebElement. This is error-prone and would result in java.lang.ClassCastException. The correct approach is to use the driver.findElement() method.
WebElement result = driver.findElement(By.cssSelector("div.page_header"));