Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在嵌入式Tomcat中使用PowerMock_Java_Unit Testing_Tomcat_Powermock_Powermockito - Fatal编程技术网

Java 在嵌入式Tomcat中使用PowerMock

Java 在嵌入式Tomcat中使用PowerMock,java,unit-testing,tomcat,powermock,powermockito,Java,Unit Testing,Tomcat,Powermock,Powermockito,我试图模拟一个由嵌入式Tomcat实例调用的静态方法。这是我的测试课: @RunWith(PowerMockRunner.class) @PrepareForTest(ExternalAPI.class) @PowerMockIgnore({"javax.management.*"}) public class TestExternalAPI { @Before public void setup() { Tomcat tomcat = new Tomcat()

我试图模拟一个由嵌入式Tomcat实例调用的静态方法。这是我的测试课:

@RunWith(PowerMockRunner.class)
@PrepareForTest(ExternalAPI.class)
@PowerMockIgnore({"javax.management.*"})
public class TestExternalAPI
{

    @Before
    public void setup() {
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);
        tomcat.enableNaming();
        tomcat.addWebapp("/app", new File("src/test/webapp").getAbsolutePath());
        tomcat.start();
    }

    @Test
    public void testAPI() {
        mockStatic(ExternalAPI.class);
        when(ExternalAPI.getData()).thenReturn(new Data());

        //call Tomcat triggering the call to ExternalAPI.getData()
    }
}
通过此配置,我得到以下异常:

java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet
    at org.apache.tomcat.util.IntrospectionUtils.callMethod1(IntrospectionUtils.java:849)
    at org.apache.tomcat.util.digester.SetNextRule.end(SetNextRule.java:201)
    at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:1060)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1783)
...
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl cannot be cast to javax.xml.parsers.SAXParserFactory
    at javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:190)
    ... 54 more
现在我想也许我需要告诉PowerMock忽略org.apache.*包,但是我得到了这个例外:

java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet
    at org.apache.tomcat.util.IntrospectionUtils.callMethod1(IntrospectionUtils.java:849)
    at org.apache.tomcat.util.digester.SetNextRule.end(SetNextRule.java:201)
    at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:1060)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1783)
...
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl cannot be cast to javax.xml.parsers.SAXParserFactory
    at javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:190)
    ... 54 more
我还尝试忽略所有org.*包,这是可行的,但是ExternalAPI.getData()方法根本没有被模仿。我想之所以会发生这种情况,是因为在本例中没有模拟来自Tomcat实例的任何内容,因为我们忽略了那些org.apache.*包

为什么会出现这些异常?我应该如何配置PowerMock


编辑:我正在使用Tomcat7。如果未使用PowerMock,则使用嵌入式Tomcat实例测试运行良好。

我认为在嵌入式模式下使用Tomcat时,应该设置所有必需的内容,如协议、生命周期侦听器(如果有)、servlet类、上下文参数

为我工作的示例代码

    tomcat = new Tomcat();

    // Trigger loading of catalina.properties
    CatalinaProperties.getProperty("foo");

    File appBase = new File(getTemporaryDirectory(), "webapps");
    if (!appBase.exists() && !appBase.mkdir()) {
        Assert.fail("Unable to create appBase for test");
    }

    String protocol = getProtocol();

    Connector connector = new Connector(protocol);
    // Listen only on localhost
    connector.setAttribute("address",
    InetAddress.getByName("localhost").getHostAddress());
    // Use random free port
    connector.setPort(0);
    // Mainly set to reduce timeouts during async tests
    connector.setAttribute("connectionTimeout", "3000");
    tomcat.getService().addConnector(connector);
    tomcat.setConnector(connector);

    // Add AprLifecycleListener if we are using the Apr connector
    if (protocol.contains("Apr")) {
        StandardServer server = (StandardServer) tomcat.getServer();
        AprLifecycleListener listener = new AprLifecycleListener();
        listener.setSSLRandomSeed("/dev/urandom");
        server.addLifecycleListener(listener);
        connector.setAttribute("pollerThreadCount", Integer.valueOf(1));
    }

    File catalinaBase = getTemporaryDirectory();
    tomcat.setBaseDir(catalinaBase.getAbsolutePath());
    tomcat.getHost().setAppBase(appBase.getAbsolutePath());

    System.setProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE", "true");

    Context ctx = tomcat.addContext(getContext(), appBase.getAbsolutePath());
    ctx.setParentClassLoader(EmbeddedTomcatTestBase.class.getClassLoader());
    //Set execution independent of current thread context classloader (compatibility with exec:java mojo)

    Wrapper w = Tomcat.addServlet(ctx, "ServletName", ServletClass.class.getName());
    w.setLoadOnStartup(1);
    w.addMapping("/ServletURI/*");
    w.addMapping("/ServletURI");
    w.addInitParameter("StatusPage", "/diagnostic/status.jsp");


    Wrapper w1 = Tomcat.addServlet(ctx, "statusJSP", JspServlet.class.getName());
    w1.addMapping("/diagnostic/status.jsp");

    Wrapper w3 = Tomcat.addServlet(ctx, "errorJSP", JspServlet.class.getName());
    w3.addMapping("/diagnostic/error.jsp");


    ctx.addParameter("EmbeddedMode", "true");

    ctx.addApplicationListener(ServletContextListnereClass.class.getName());

    ContextConfig contextConfig = new ContextConfig();
    ctx.addLifecycleListener(contextConfig);

    Tomcat.initWebappDefaults(ctx);
    tomcat.start();


   // initialize your engine / invoke any java methods of your interest here..

我认为在嵌入式模式下使用tomcat时,应该设置所有必需的内容,比如协议、生命周期侦听器(如果有)、servlet类、上下文参数

为我工作的示例代码

    tomcat = new Tomcat();

    // Trigger loading of catalina.properties
    CatalinaProperties.getProperty("foo");

    File appBase = new File(getTemporaryDirectory(), "webapps");
    if (!appBase.exists() && !appBase.mkdir()) {
        Assert.fail("Unable to create appBase for test");
    }

    String protocol = getProtocol();

    Connector connector = new Connector(protocol);
    // Listen only on localhost
    connector.setAttribute("address",
    InetAddress.getByName("localhost").getHostAddress());
    // Use random free port
    connector.setPort(0);
    // Mainly set to reduce timeouts during async tests
    connector.setAttribute("connectionTimeout", "3000");
    tomcat.getService().addConnector(connector);
    tomcat.setConnector(connector);

    // Add AprLifecycleListener if we are using the Apr connector
    if (protocol.contains("Apr")) {
        StandardServer server = (StandardServer) tomcat.getServer();
        AprLifecycleListener listener = new AprLifecycleListener();
        listener.setSSLRandomSeed("/dev/urandom");
        server.addLifecycleListener(listener);
        connector.setAttribute("pollerThreadCount", Integer.valueOf(1));
    }

    File catalinaBase = getTemporaryDirectory();
    tomcat.setBaseDir(catalinaBase.getAbsolutePath());
    tomcat.getHost().setAppBase(appBase.getAbsolutePath());

    System.setProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE", "true");

    Context ctx = tomcat.addContext(getContext(), appBase.getAbsolutePath());
    ctx.setParentClassLoader(EmbeddedTomcatTestBase.class.getClassLoader());
    //Set execution independent of current thread context classloader (compatibility with exec:java mojo)

    Wrapper w = Tomcat.addServlet(ctx, "ServletName", ServletClass.class.getName());
    w.setLoadOnStartup(1);
    w.addMapping("/ServletURI/*");
    w.addMapping("/ServletURI");
    w.addInitParameter("StatusPage", "/diagnostic/status.jsp");


    Wrapper w1 = Tomcat.addServlet(ctx, "statusJSP", JspServlet.class.getName());
    w1.addMapping("/diagnostic/status.jsp");

    Wrapper w3 = Tomcat.addServlet(ctx, "errorJSP", JspServlet.class.getName());
    w3.addMapping("/diagnostic/error.jsp");


    ctx.addParameter("EmbeddedMode", "true");

    ctx.addApplicationListener(ServletContextListnereClass.class.getName());

    ContextConfig contextConfig = new ContextConfig();
    ctx.addLifecycleListener(contextConfig);

    Tomcat.initWebappDefaults(ctx);
    tomcat.start();


   // initialize your engine / invoke any java methods of your interest here..

谢谢你的例子,但是嵌入式Tomcat对我来说工作得很好。这个问题只有在我尝试使用PowerMock时才会出现。谢谢你的例子,但是嵌入式Tomcat对我来说工作得很好。只有当我尝试使用PowerMock时,问题才会出现。我不确定我是否理解您在这里真正想要实现的目标。通常在单元测试中,您将模拟代码所依赖的依赖项,然后调用代码并确保它正确使用模拟。除非你写的是Tomcat,否则我不知道你为什么要嵌入Tomcat而不是嘲笑它。您在最下面描述的场景是集成测试的完美示例,您也应该这样做。但是我在这里没有单元测试场景。@dcsohl我想测试这个web应用程序的整个流程。但是,我希望模拟在该流期间触发的外部调用,以便在运行测试时不需要外部系统。我试图通过在嵌入式Tomcat实例上部署应用程序,然后向其发送REST调用来实现这一点。这都是遗留应用程序的一部分,该应用程序已经有一些使用这种方法的测试,因此完全重构它们并不是一个真正的选项。我不确定我是否理解您在这里实际要完成的任务。通常在单元测试中,您将模拟代码所依赖的依赖项,然后调用代码并确保它正确使用模拟。除非你写的是Tomcat,否则我不知道你为什么要嵌入Tomcat而不是嘲笑它。您在最下面描述的场景是集成测试的完美示例,您也应该这样做。但是我在这里没有单元测试场景。@dcsohl我想测试这个web应用程序的整个流程。但是,我希望模拟在该流期间触发的外部调用,以便在运行测试时不需要外部系统。我试图通过在嵌入式Tomcat实例上部署应用程序,然后向其发送REST调用来实现这一点。这都是遗留应用程序的一部分,该应用程序已经有一些使用这种方法的测试,因此完全重构它们并不是一个真正的选项。