5

I'm trying to use WireMock in my JUnit tests to mock calls to an external API.

public class ExampleWiremockTest {

    @Rule
    public WireMockRule wireMockRule = new WireMockRule(9999);

    @Before
    public void setUp() {
        stubFor(get(urlEqualTo("/bin/sillyServlet"))
            .willReturn(aResponse()
                .withStatus(200)
                .withBody("Hello WireMock!")
            )
        );

    }

    @Test
    public void testNothing() throws URISyntaxException, IOException {
        URI uri = new URIBuilder().setScheme("http")
            .setHost("localhost")
            .setPort(9999)
            .setPath("/bin/sillyServlet")
            .build();
        HttpGet httpGet = new HttpGet(uri);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        String body = EntityUtils.toString(entity);
        assertThat(body, is("Hello WireMock!"));
    }

}

The code compiles but when I run my test, WireMock throws an HTTP 500 that seems to be caused by an inconsistency in the underlying Servlet API version.

Running com.example.core.ExampleWiremockTest
[main] INFO wiremock.org.eclipse.jetty.util.log - Logging initialized @1030ms
[main] INFO wiremock.org.eclipse.jetty.server.Server - jetty-9.2.z-SNAPSHOT
[main] INFO wiremock.org.eclipse.jetty.server.handler.ContextHandler - Started w.o.e.j.s.ServletContextHandler@ef9296d{/__admin,null,AVAILABLE}
[main] INFO wiremock.org.eclipse.jetty.server.handler.ContextHandler - Started w.o.e.j.s.ServletContextHandler@659a969b{/,null,AVAILABLE}
[main] INFO wiremock.org.eclipse.jetty.server.NetworkTrafficServerConnector - Started NetworkTrafficServerConnector@723d73e1{HTTP/1.1}{0.0.0.0:9999}
[main] INFO wiremock.org.eclipse.jetty.server.Server - Started @1168ms
[qtp436546048-16] INFO /__admin - RequestHandlerClass from context returned com.github.tomakehurst.wiremock.http.AdminRequestHandler. Normalized mapped under returned 'null'
[qtp436546048-20] INFO / - RequestHandlerClass from context returned com.github.tomakehurst.wiremock.http.StubRequestHandler. Normalized mapped under returned 'null'
[qtp436546048-20] WARN wiremock.org.eclipse.jetty.servlet.ServletHandler - Error for /bin/sillyServlet
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.getHeader(Ljava/lang/String;)Ljava/lang/String;
        at wiremock.org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:322)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
        at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
        at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
        at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at wiremock.org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
        at wiremock.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
        at wiremock.org.eclipse.jetty.server.Server.handle(Server.java:499)
        at wiremock.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
        at wiremock.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
        at wiremock.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
        at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
        at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
        at java.lang.Thread.run(Thread.java:745)
[qtp436546048-20] WARN wiremock.org.eclipse.jetty.server.HttpChannel - /bin/sillyServlet
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted()Z
        at wiremock.org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:684)
        at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
        at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
        at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at wiremock.org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
        at wiremock.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
        at wiremock.org.eclipse.jetty.server.Server.handle(Server.java:499)
        at wiremock.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
        at wiremock.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
        at wiremock.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
        at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
        at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
        at java.lang.Thread.run(Thread.java:745)
[qtp436546048-20] WARN wiremock.org.eclipse.jetty.server.HttpChannel - Could not send response error 500: java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted()Z
[main] INFO wiremock.org.eclipse.jetty.server.NetworkTrafficServerConnector - Stopped NetworkTrafficServerConnector@723d73e1{HTTP/1.1}{0.0.0.0:9999}
[main] INFO wiremock.org.eclipse.jetty.server.handler.ContextHandler - Stopped w.o.e.j.s.ServletContextHandler@659a969b{/,null,UNAVAILABLE}
[main] INFO wiremock.org.eclipse.jetty.server.handler.ContextHandler - Stopped w.o.e.j.s.ServletContextHandler@ef9296d{/__admin,null,UNAVAILABLE}
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.577 sec <<< FAILURE! - in com.example.core.ExampleWiremockTest

I do have other libraries in my classpath that rely on different versions of Jetty, which I suppose is the cause of the problem.

WireMock uses Jetty 9.2.13, I also have a transitive dependency on Cobertura, which relies on 6.1.14

I was originally trying to use the following dependency:

<dependency>
    <groupId>com.github.tomakehurst</groupId>
    <artifactId>wiremock</artifactId>
    <version>2.6.0</version>
</dependency>

I switched to the standalone Jar version, hoping it would help me avoid the conflict but the result is exactly the same.

<dependency>
    <groupId>com.github.tomakehurst</groupId>
    <artifactId>wiremock-standalone</artifactId>
    <version>2.6.0</version>
</dependency>
toniedzwiedz
  • 17,895
  • 9
  • 86
  • 131

3 Answers3

6

Check your servlet-api version, you likely are using an old version.

Both of those methods were added in Servlet 3.0

You probably have the Servlet 2.5 (or Servlet 2.4) jar in your classpath.

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
  • Yes, I'm aware of that. One of the libraries I'm using has a dependency on `cobertura`, which has a dependency on `servlet-api-2.5`. I was looking for a way to work around this problem. – toniedzwiedz Apr 11 '17 at 07:08
  • Not possible. You have to select a single servlet-api for your project, you cannot have multiple. Since you are using Jetty 9.2.x, I would recommend using Servlet 3.1. Cobertura wont care that a newer servlet api exists, but everything else will care about the older servlet-api. – Joakim Erdfelt Apr 11 '17 at 15:05
  • Excluding the implicit servlet API dependency introduced by Cobertura did the trick, see the other answer. – toniedzwiedz Apr 11 '17 at 15:17
2

For those who lend to this ticket while using wiremock-jre8 (with transitive Jetty 9) when upgrading to Java 17/Spring Boot 3/Spring 6 having NoSuchMethodError: NetworkTrafficServerConnector.addNetworkTrafficListener: Migrate to wiremock-standalone

See more: https://github.com/wiremock/wiremock/issues/1760#issuecomment-1234404609

radistao
  • 14,889
  • 11
  • 66
  • 92
1

As mentioned, in the question, one of the libraries I was using had a dependency on Cobertura, which in turn introducde a dependency on Servlet API 2.5 (both as a transitive dependency via an older verison of Jetty and a direct dependency).

Cobertura dependency

Excluding the artifact from the original dependency (the one dependent on cobertura) allowed me to run my test successfully.

<dependency>
    <groupId>com.cognifide.slice</groupId>
    <artifactId>slice-core-api</artifactId>
    <version>${slice.version}</version>
    <scope>provided</scope>
    <exclusions>
        <exclusion>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>servlet-api-2.5</artifactId>
        </exclusion>
    </exclusions>
</dependency>
toniedzwiedz
  • 17,895
  • 9
  • 86
  • 131