2016-09-07 25 views
1

埋め込みTomcatインスタンスによって呼び出される静的メソッドをモックしようとしています。ここに私のテストクラスは次のとおりです。この構成で埋め込みTomcatでPowerMockを使用する

@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) 
... 

は今、私はパッケージ*多分私はorg.apacheを無視するPowerMockを伝える必要があると思ったが、 *作品のパッケージを、私はまた、すべての組織を無視して試してみました

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 

が、その後ExternalAPI.getData()メソッドは、すべての嘲笑されていません:私はこの例外を取得します。このケースでは、Tomcatインスタンスからの何も嘲笑されていないからです。なぜなら、これらのorg.apache。*パッケージを無視しているからです。

なぜこれらの例外が発生し、どのようにPowerMockを構成する必要がありますか?

編集:私はTomcat 7を使用しています。PowerMockが使用されていない場合は、埋め込まれたTomcatインスタンスを使用してテストが正常に実行されます。

+0

ここで実際に達成しようとしていることがわかりません。通常、単体テストでは、コードが依存している依存関係を模倣し、コードを呼び出し、モックを適切に使用するようにします。 * Tomcat *を書いていない限り、Tomcatを嘲笑するのではなく、なぜTomcatを埋め込んでいるのか分かりません。一番下に記述するシナリオは、*統合テスト*の完全な例です。これらのテストも同様に行う必要があります。しかし、私はここで単体テストシナリオを取得しません。 – dcsohl

+0

@dcsohlこのWebアプリケーションのフロー全体をテストしたいと思います。しかし、私は、そのフロー中にトリガされた外部呼び出しを模擬したいので、テストを実行するときに外部システムは必要ありません。私は埋め込まれたTomcatのインスタンスにアプリケーションを展開し、それにREST呼び出しを送信することによってこれをしようとしています。これは、このアプローチを使用するいくつかのテストをすでに持っているレガシーアプリケーションの一部です。したがって、完全にリファクタリングすることは実際の選択肢ではありません。 –

答えて

0

私はあなたが私のために働いていたいずれかの場合には、プロトコル、ライフ・サイクル・リスナーのような組み込みモードでTomcatを使用して、サーブレットクラス、コンテキストパラメータ...

サンプルコード必要なすべてのものを設定すべきだと思う...

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.. 
+0

この例をありがとうが、埋め込まれたTomcatはうまく動作しています。この問題は、PowerMockを使用しようとしたときにのみ表示されます。 –

関連する問題