I am facing this 'Cannot insantiate class'
error on running one of my test cases in Selenium webdriver using Java.
Below is the class of the functionality of the test,
package Pages;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import Lib.lib;
public class KnowledgeBase extends lib{
By sortBylink = By.xpath("html/body/div[1]/featured-studies-grid/div[2]/featured-studies-toolbar/div/div[2]/div[2]/div/div");
By featuredOption = By.xpath("html/body/div[1]/featured-studies-grid/div[2]/featured-studies-toolbar/div/div[2]/div[2]/div/ul/li[1]");
By mostRcnt = By.xpath("html/body/div[1]/featured-studies-grid/div[2]/featured-studies-toolbar/div/div[2]/div[2]/div/ul/li[2]");
String featOption = driver.findElement(By.xpath("html/body/div[1]/featured-studies-grid/div[2]/featured-studies-toolbar/div/div[2]/div[2]/div/ul/li[1]")).getText();
String mostRecent = driver.findElement(By.xpath("html/body/div[1]/featured-studies-grid/div[2]/featured-studies-toolbar/div/div[2]/div[2]/div/ul/li[2]")).getText();
public void initSBy() throws Exception
{
driver.findElement(sortBylink).click();
Thread.sleep(1500);
}
public void selectfO() throws Exception
{
driver.findElement(featuredOption).click();
Thread.sleep(5000);
}
public void selectMr() throws Exception
{
driver.findElement(mostRcnt).click();
Thread.sleep(5000);
}
public void sortBy(String sProp) throws Exception
{
this.initSBy();
if (sProp == "featOption") {
this.selectfO();
}
else if (sProp == "mostRecent"){
this.selectMr();
}
else {
System.out.println("Incorrect option. Test failed.");
}
}
}
Below is my Test Case Class
package TestCases;
import org.testng.annotations.Test;
import Lib.lib;
import Pages.KnowledgeBase;
import Pages.LoginPage;
public class sortingTextKB extends lib {
LoginPage uLogin = new LoginPage();
KnowledgeBase sortObj = new KnowledgeBase();
//Logging In
@Test (priority = 1)
public void loggingIn() throws Exception
{
uLogin.loginToKB("[email protected]", "uziiiii");
}
//Sorting
@Test (priority = 2)
public void sortIn() throws Exception
{
sortObj.sortBy("Most Recent");
}
}
Below is my Lib class, that contains the chrome driver configuration
package Lib;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.AfterTest;
public class lib {
protected static WebDriver driver = null;
@BeforeTest
public void chrome_extension()
{
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
driver = new ChromeDriver(options);
driver.get("http://www.testsite.com");
}
@AfterTest
public void quit()
{
driver.quit();
}
}
When I run my test case class, I am getting the following error,
org.testng.TestNGException:
Cannot instantiate class TestCases.sortingTextKB
at org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:38)
at org.testng.internal.ClassHelper.createInstance1(ClassHelper.java:387)
at org.testng.internal.ClassHelper.createInstance(ClassHelper.java:299)
at org.testng.internal.ClassImpl.getDefaultInstance(ClassImpl.java:110)
at org.testng.internal.ClassImpl.getInstances(ClassImpl.java:186)
at org.testng.internal.TestNGClassFinder.<init>(TestNGClassFinder.java:120)
at org.testng.TestRunner.initMethods(TestRunner.java:409)
at org.testng.TestRunner.init(TestRunner.java:235)
at org.testng.TestRunner.init(TestRunner.java:205)
at org.testng.TestRunner.<init>(TestRunner.java:160)
at org.testng.remote.RemoteTestNG1ドル.newTestRunner(RemoteTestNG.java:141)
at org.testng.remote.RemoteTestNG$DelegatingTestRunnerFactory.newTestRunner(RemoteTestNG.java:271)
at org.testng.SuiteRunner$ProxyTestRunnerFactory.newTestRunner(SuiteRunner.java:561)
at org.testng.SuiteRunner.init(SuiteRunner.java:157)
at org.testng.SuiteRunner.<init>(SuiteRunner.java:111)
at org.testng.TestNG.createSuiteRunner(TestNG.java:1299)
at org.testng.TestNG.createSuiteRunners(TestNG.java:1286)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:29)
... 21 more
Caused by: java.lang.NullPointerException
at Pages.KnowledgeBase.<init>(KnowledgeBase.java:22)
at TestCases.sortingTextKB.<init>(sortingTextKB.java:12)
... 26 more
Following is line 22 of KnowledgeBase
class,
String featOption = driver.findElement(By.xpath("html/body/div[1]/featured-studies-grid/div[2]/featured-studies-toolbar/div/div[2]/div[2]/div/ul/li[1]")).getText();
Please let me know why I am facing this 'cannot instantiate class'
error. Thanks
-
BTW, package names should be lower case, and class names should start from Capital letter in Java.dzieciou– dzieciou2015年12月14日 10:07:45 +00:00Commented Dec 14, 2015 at 10:07
-
Rename ClassName of Lib to another. I also got an error.This can be resolved by changing Classname.vinay goswami– vinay goswami2018年01月26日 15:50:09 +00:00Commented Jan 26, 2018 at 15:50
5 Answers 5
It looks like your driver
instance is created in one class(lib
, (should start with Capital letter BTW)) but you are trying to access it in another class(KnowledgeBase
).
If you want to use a class instance in another class, you have options. Some of them are:
- Add a getter method. Add a
public getDriverInstance()
method in the class where the instance is created that will just return thedriver
instance. - Keep everything in the same class. Keep the driver initialization method as well as the tests themselves in the same class. That's obviously a messy solution but it will work.
- Use a Dependency Injection framework. You can use a DI framework like Spring, PicoContainer, etc.., which is probably the cleanest solution but has some learning curve to it.
Use @BeforeMethod annotation in place of @BeforeTest.
-
Just curious, what does this do? What other impacts does this change make?2015年09月14日 04:15:51 +00:00Commented Sep 14, 2015 at 4:15
-
It’s purely intuitive; there aren’t any issues in the code. So either user14403 has made a logical error in loginToKB method (for which code isn’t shared) or since details are specified in BeforeTest and it is expected to call this before each Test (priority=1) and Test2 (priority=2), to achieve this BeforeMethod has to be used (this being a common mistake made).JustARandomGuy– JustARandomGuy2015年09月14日 04:36:32 +00:00Commented Sep 14, 2015 at 4:36
-
1The explanation of the difference between
@BeforeMethod
and@BeforeTest
needs to be in your answer.Kate Paulk– Kate Paulk2015年09月14日 11:12:51 +00:00Commented Sep 14, 2015 at 11:12 -
@KatePaulk Explaining the difference would be a great idea, because it's a confusing concept in TestNG.
@BeforeMethod
runs before each@Test
method.@BeforeTest
runs before each test, which is not the same thing as a@Test
method. A TestNG test is defined in the XML or JSON file that defines what to run. It's essentially a sub-suite, and can invoke many test methods. Yeah, like I said, confusing. That said, explaining the difference would not help this answer, because (while it may be a good idea) it does not solve the problem described in the question.Dale Emery– Dale Emery2018年01月26日 22:09:11 +00:00Commented Jan 26, 2018 at 22:09
There are a few problems here. The construction of your classes is confusing and will give you issues if not corrected.
First, @BeforeTest
is run once before the entire suite of tests (This is a common error). You would instead want either @BeforeClass
or @BeforeMethod
. @BeforeMethod
would be a better choice as it would ensure a fresh browser before each test method. You'll need a matching @AfterMethod
as well.
Next, you are extending all of your Classes from the same Lib class. This is a very unwieldy design pattern. Instead create a class with all of your test setup and tear down. Extend the classes with the actual tests from this.
From here you can pass the driver to the Page objects and Knowledgebase object using a getdriver()
method as suggested by Eugene.
public class ChromeTest {
private ChromeDriver driver;
@BeforeMethod
public void beforeMethod(){
driver = new ChromeDriver();
//additional setup
}
@AfterMethod
public void afterMethod(){
driver.quit();
//additional tear down
}
public ChromeDriver getDriver (){
return driver;
}
}
Test Classes
public class UiTest extends ChromeTest {
@Test
public void test1(){
KnowledgeBase kb = new KnowledgeBase(getDriver());
//Rest of your test code
}
}
Refactor your page and KnowledgeBase classes to use the passed in driver instance.
public class KnowledgeBase{
private WebDriver driver;
public KnowledgeBase( WebDriver webDriver ) {
driver = webDriver;
}
//rest of your methods
}
By refactoring your classes and methods as noted above it will vastly simplify your code which will make the logical errors easier to find if not fix it outright.
The problem is this:
- TestNG must finish instantiating a
KnowledgeBase
object before it calls any of the configuration methods (annotated with@BeforeTest
and@BeforeMethod
). - Instantiating a
KnowledgeBase
includes initializing all of its members. - One of the members it must initialize is
featOption
, on line 22. - In order to initialize
featOption
, the initialization tries to calldriver.findElement(...)
. - Because the
chrome_extension()
method inLib
hasn't been called yet,driver
is stillnull
. - Kaboom
To fix this, either:
- Initialize
driver
in a constructor (probably inLib
), and only then initializefeatOption
(probably inKnowledgeBase
's constructor). This means you'll have a singledriver
instance for all of your tests. Given that you're currently launching a new driver for each TestNG test (confusingly, in TestNG a "test" is not at all the same thing as a test method, even though test methods are annotated with@Test
), that may or may not be what you want. - Initialize
driver
at the point where you declare it inLib
. This is more or less like initializing it in a constructor. So again, this may or may not be what you want. - Initialize
featOption
in a configuration method (annotated as@BeforeTest
or@BeforeMethod
) inKnowledgeBase
. This will be called after thechrome_extension()
method inLib
, so thedriver
will have have been constructed and launched. So when you calldriver.findElement(...)
, driver will be valid.
Can you change:
protected static WebDriver driver = null;
to
public static WebDriver driver;
Maybe that works. Just a try.
Explore related questions
See similar questions with these tags.