java 使用 TestNG 运行代码时出现空指针异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29065095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 14:37:22  来源:igfitidea点击:

Null Pointer Exception while running code using TestNG

javaseleniumselenium-webdrivernullpointerexceptiontestng

提问by Ashwiinn Karaangutkar

I am trying to automate a Login and Logout Scenario in TestNG and passing the browser as parameter from XML on the basis of which chromedriver() instance will be created and the code will run.I have two classes TestRunner and Login where login method gets data (username and password) TestRunner and data is fetched from excel.Exception e is getting null value as I found out while debugging. Any way to fix it?

我正在尝试在 TestNG 中自动化登录和注销场景,并根据将创建 chromedriver() 实例并运行代码的基础上将浏览器作为参数从 XML 传递。我有两个类 TestRunner 和 Login 其中登录方法获取数据(用户名和密码)TestRunner 和数据是从 excel.Exception e 获取空值,因为我在调试时发现。有什么办法可以解决吗?

FAILED: Registration_data("[email protected]", "ashwin123")
java.lang.NullPointerException
at com.DataDriven.Login.login(Login.java:68)
at com.DataDriven.TestRunner.Registration_data(TestRunner.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at   org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at     org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:12)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
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)


    package com.DataDriven;
    import java.util.concurrent.TimeUnit;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    public class TestRunner {

    @Test(dataProvider = "Authentication")
    public static void Registration_data(String sUserName, String sPassword)
        throws Exception {

    Login lp = new Login();
    lp.login(sUserName, sPassword);
    }

    @DataProvider
    public Object[][] Authentication() throws Exception {

    Object[][] testObjArray = ReadData.getTableArray(
            "F:\Automation\DataDrivenPractice\DataFiles\DataFile.xlsx",
            "Sheet1");

    return (testObjArray);  }  }


    package com.DataDriven;

    import java.io.File;

    import org.apache.commons.io.FileUtils;
    import org.openqa.selenium.By;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.TakesScreenshot;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeDriver;

    public class Login {
     WebDriver driver = null;

     @Parameters("browser")
     @BeforeClass
    // Passing Browser parameter from TestNG xml
    public void beforeTest(String browser) {

    // If the browser is Firefox, then do this

    if (browser.equalsIgnoreCase("firefox")) {

        driver = new FirefoxDriver();

        // If browser is IE, then do this

      } else if (browser.equalsIgnoreCase("chrome")) {

        // Here I am setting up the path for my IEDriver

        driver = new ChromeDriver(); } }

     public void login(String username, String password) {
        try {
        driver.get("https://www.facebook.com/");

        driver.findElement(By.id("email")).sendKeys(username);
        driver.findElement(By.id("pass")).sendKeys(password);
        driver.findElement(By.id("loginbutton")).click();
        driver.findElement(By.linkText("Log Out")).click();
         }

       catch (Exception e) {
        File srcfile = ((TakesScreenshot) driver)
                .getScreenshotAs(OutputType.FILE);

        try {
            FileUtils.copyFile(srcfile, new File(
                    "F:\Automation\Screenshots\Login.jpg"));
        } catch (Exception e1) {
            e1.printStackTrace();
        }   }  }}


        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
        <suite name="Suite" parallel="none">
        <test name="FirefoxTest">
         <parameter name="browser" value="chrome" />
         <classes>
         <class name="com.DataDriven.TestRunner" />
         <class name="com.DataDriven.Login" /> 
         </classes>
         </test>
         </suite>

回答by Fenio

Your problem is - your method beforeTestdoesn't invoke. Your driverdoesn't point to any type of object.

你的问题是 - 你的方法beforeTest没有调用。你driver没有指向任何类型的对象。

TestNG search through all your classes only for @Testannotation. How it's supposed to know that @BeforeClassannotation lies in specific class you've created?

TestNG 搜索您所有的类只是为了@Test注释。它应该如何知道@BeforeClass注释位于您创建的特定类中?

To run @BeforeClassannotation, you either have to set extendsfor Loginclass (it won't be effective for multiple scripts) or run beforeTestmethod manually. Or set it to running class containing @Testannotation.

要运行@BeforeClass注释,您必须extendsLogin类设置(它不会对多个脚本有效)或beforeTest手动运行方法。或者将其设置为包含@Test注释的运行类。

Correct me if i'm wrong. Hope it helps!

如我错了请纠正我。希望能帮助到你!

EDIT:

编辑:

Move your method and WebDriver variable to Test RunnerClass

将您的方法和 WebDriver 变量移动到Test RunnerClass

 WebDriver driver = null;

 @Parameters("browser")
 @BeforeClass
// Passing Browser parameter from TestNG xml
public void beforeTest(String browser) {

// If the browser is Firefox, then do this

if (browser.equalsIgnoreCase("firefox")) {

    driver = new FirefoxDriver();

    // If browser is IE, then do this

  } else if (browser.equalsIgnoreCase("chrome")) {

    // Here I am setting up the path for my IEDriver

    driver = new ChromeDriver(); } }

TestRunnerclass should contain both, @Testand @BeforeClass. As TestNG reads Annotations from classes containing @Testannotation.

TestRunner类应该同时包含,@Test@BeforeClass。当 TestNG 从包含@Test注解的类中读取注解时。

回答by Nguyen Vu Hoang

There are many issues in your scripts

你的脚本有很多问题

1 - Your classes init separately. The driver from @BeforeClass doesnot inherite into your @Test

1 - 您的课程单独初始化。来自 @BeforeClass 的驱动程序不会继承到您的 @Test

2 - When you do

2 - 当你这样做时

Login lp = new Login();

you have

你有

WebDriver driver = null;
@BeforeClass is not invoked, no driver init, your driver is still null

Then

然后

lp.login(sUserName, sPassword);

NullPointException throws because driver in following line of code is null

NullPointException 抛出,因为以下代码行中的驱动程序为空

driver.get("https://www.facebook.com/");

Suggest action

建议行动

  • You need to get driver goes through all your classes
  • 你需要让司机完成你所有的课程

TestBase.class

测试库类

Put your @BeforeClass here

LoginPage.class, be sure you allow to cast driver into it

LoginPage.class,确保您允许将驱动程序转换到其中

public LoginPage(WebDriver driver) {
    // your code here
}    

// Put login(sUserName, sPassword) method here

TestRunner.class

TestRunner.class

inherite/extends from TestBase.class
LoginPage lp = new LoginPage(driver);
lp.login(sUserName, sPassword);