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

在Tomcat中运行Cucumber-TestNG的Servlet时出现空指针异常求助

Tomcat中通过Servlet触发Cucumber+TestNG执行时遭遇NullPointerException

我尝试在Tomcat服务器中运行一个Servlet来触发Cucumber测试,Servlet代码如下:

package com.revature.http; 
import java.io.File; 
import java.io.IOException; 
import java.util.List; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.testng.ITestNGListener; 
import org.testng.TestListenerAdapter; 
import org.testng.TestNG; 
import org.testng.collections.Lists; 

public class RunCucumber extends HttpServlet { 
    private static final long serialVersionUID = 1L; 

    public RunCucumber() { 
        super(); 
        // TODO Auto-generated constructor stub 
    } 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
        TestListenerAdapter adapter = new TestListenerAdapter(); 
        TestNG testng = new TestNG(); 
        testng.setTestClasses(new Class[] { com.revature.cucumber.CucumberRunner.class }); 
        testng.addListener((ITestNGListener) adapter); 
        testng.run(); 
    } 

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
        // TODO Auto-generated method stub 
        doGet(request, response); 
    } 
}

但每次调用这个Servlet时,都会抛出如下空指针异常:

[Utils] [ERROR] [Error] java.lang.NullPointerException at cucumber.api.testng.AbstractTestNGCucumberTests.features(AbstractTestNGCucumberTests.java:29) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
at java.lang.reflect.Method.invoke(Unknown Source) 
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:108) 
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:55) 
at org.testng.internal.MethodInvocationHelper.invokeMethodNoCheckedException(MethodInvocationHelper.java:45) 
at org.testng.internal.MethodInvocationHelper.invokeDataProvider(MethodInvocationHelper.java:115) 
at org.testng.internal.Parameters.handleParameters(Parameters.java:509) 
at org.testng.internal.Invoker.handleParameters(Invoker.java:1308) 
at org.testng.internal.Invoker.createParameters(Invoker.java:1036) 
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1126) 
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126) 
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) 
at org.testng.TestRunner.privateRun(TestRunner.java:744) 
at org.testng.TestRunner.run(TestRunner.java:602) 
at org.testng.SuiteRunner.runTest(SuiteRunner.java:380) 
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:375) 
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340) 
at org.testng.SuiteRunner.run(SuiteRunner.java:289) 
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) 
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) 
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1301) 
at org.testng.TestNG.runSuitesLocally(TestNG.java:1226) 
at org.testng.TestNG.runSuites(TestNG.java:1144) 
at org.testng.TestNG.run(TestNG.java:1115) 
at com.revature.http.RunCucumber.doGet(RunCucumber.java:44) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) 
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) 
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) 
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) 
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
at java.lang.Thread.run(Unknown Source)

请求协助排查并解决该空指针异常问题。


问题分析与解决方案

这个空指针异常发生在AbstractTestNGCucumberTests.features()方法的第29行,核心原因是Cucumber无法正确加载feature文件或初始化测试上下文,下面是几个针对性的解决步骤:

1. 检查CucumberRunner类的配置完整性

你的CucumberRunner类必须继承AbstractTestNGCucumberTests,并且通过@CucumberOptions明确指定feature文件路径和步骤定义包,示例如下:

package com.revature.cucumber;

import cucumber.api.CucumberOptions;
import cucumber.api.testng.AbstractTestNGCucumberTests;

@CucumberOptions(
    features = "classpath:features", // 对应resources目录下的features文件夹
    glue = "com.revature.stepdefinitions" // 步骤定义类所在的包
)
public class CucumberRunner extends AbstractTestNGCucumberTests {
}

如果features路径错误或者feature文件缺失,Cucumber会因无法找到测试资源抛出NPE。

2. 确保feature文件在Tomcat类路径中

部署到Tomcat时,feature文件必须被打包到WEB-INF/classes目录下。如果是Maven项目,把feature文件放在src/main/resources/features目录下,Maven会自动将其打包到正确位置;如果是普通Web项目,手动将feature文件夹复制到WEB-INF/classes下。

3. 改用TestNG XML配置文件运行测试

在Servlet环境中直接调用testng.setTestClasses()可能会导致Cucumber上下文初始化不完整,改用TestNG XML配置文件可以更稳定地加载测试:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    TestListenerAdapter adapter = new TestListenerAdapter();
    TestNG testng = new TestNG();
    List<String> suiteFiles = Lists.newArrayList();
    // 配置文件放在WEB-INF下,获取真实路径
    suiteFiles.add(getServletContext().getRealPath("/WEB-INF/testng.xml"));
    testng.setTestSuites(suiteFiles);
    testng.addListener((ITestNGListener) adapter);
    testng.run();
}

对应的testng.xml内容:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Cucumber Test Suite">
    <test name="Cucumber Tests">
        <classes>
            <class name="com.revature.cucumber.CucumberRunner"/>
        </classes>
    </test>
</suite>

4. 验证依赖版本兼容性

Cucumber和TestNG的版本不兼容也可能导致初始化异常。比如Cucumber 4.x推荐搭配TestNG 6.14.x或7.0.x版本,你可以查看项目依赖,确保两者版本匹配。

5. 手动指定Cucumber资源路径

如果以上方法无效,可以在Servlet初始化时手动设置feature文件的系统属性,确保Cucumber能找到资源:

@Override
public void init() throws ServletException {
    super.init();
    // 设置feature文件的真实路径
    String featurePath = getServletContext().getRealPath("/WEB-INF/classes/features");
    System.setProperty("cucumber.features", featurePath);
}

内容的提问来源于stack exchange,提问作者Antonio Tapia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:35:42