I've encountered a weird issue today with verifying if a call was made to wiremock with a specific parameter. At first I thought it might be the underscore char ('_') I used, but when I wrote a test to verify if it I found a more basic case.
Analyse the code below:
@Rule
public WireMockRule wireMockRule = new WireMockRule(8090);
@Test
public void wiremockTest() {
//GIVEN
stubFor(get(urlMatching("/test.*"))
.willReturn(aResponse()
.withStatus(200)));
final Client client = ClientBuilder.newClient();
//WHEN
client.target("http://localhost:8090/test")
.queryParam("query", "param")
.request().get();
//WHEN
verify(1, getRequestedFor(urlMatching("/test.*")).withQueryParam("query", matching("param")));
}
Everything will work fine. However if the call did not contain the query parameter or we want to verify a different query parameter, like this:
verify(1, getRequestedFor(urlMatching("/test.*")).withQueryParam("queryyyyy", matching("param")));
then the test fails with this message:
com.github.tomakehurst.wiremock.client.VerificationException: Expected status 200 for http://localhost:8090/__admin/requests/count but was 500
at com.github.tomakehurst.wiremock.client.HttpAdminClient.postJsonAssertOkAndReturnBody(HttpAdminClient.java:147)
at com.github.tomakehurst.wiremock.client.HttpAdminClient.countRequestsMatching(HttpAdminClient.java:101)
at com.github.tomakehurst.wiremock.client.WireMock.verifyThat(WireMock.java:254)
at com.github.tomakehurst.wiremock.client.WireMock.verify(WireMock.java:267)
at pl.kmejka.wiremocktest.WiremockTest.wiremockTest(WiremockTest.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at com.github.tomakehurst.wiremock.junit.WireMockRule$1.evaluate(WireMockRule.java:67)
...
To run this test I had to specify these dependencies in my pom.xml:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>1.53</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.17</version>
</dependency>
Let me know if I could help you with this issue, I'd be more than glad to help, but I could use a push in the right direction as I don't know the codebase at all.
If you change the port number and want to use the static DSL, you need to tell the static client instance what the new port number is:
WireMock.configFor(8090)
Alternatively (and this is faster as it doesn't go over the wire) you can stub against the rule:
wireMockRule.stubFor(...)
How does that relate to my issue? As I said - if the query parameters in the call and in the assertion match (the assertion succeeds) everything is fine. So how is that connected with the changed port?
You're right, the rule configures the client port so that's not the issue.
I can't see any reason you'd see this behaviour from looking at the code. I'd need to get in there with the debugger.
Is WireMock logging an additional stack trace from the server, or is that stack trace all you're getting?
I posted everything I had in the gist: https://gist.github.com/kmejka/03c0b8454e0048189a95
Try adding a ConsoleNotifier to the config so it logs out the exception on the server.
Ok, I'll do that, but right now I'm caught up in other things. I'll try to test that today.
I hit this exact same problem using withQueryParam.
Was able to use Url matching to work around it.
Here is the server stack trace:
java.lang.NullPointerException
com.github.tomakehurst.wiremock.matching.RequestPattern$6.apply(RequestPattern.java:359)
com.github.tomakehurst.wiremock.matching.RequestPattern$6.apply(RequestPattern.java:354)
com.google.common.collect.Iterators.all(Iterators.java:697)
com.google.common.collect.Iterables.all(Iterables.java:632)
com.github.tomakehurst.wiremock.matching.RequestPattern.queryParametersMatch(RequestPattern.java:148)
com.github.tomakehurst.wiremock.matching.RequestPattern.isMatchedBy(RequestPattern.java:95)
com.github.tomakehurst.wiremock.verification.InMemoryRequestJournal$1.apply(InMemoryRequestJournal.java:59)
com.github.tomakehurst.wiremock.verification.InMemoryRequestJournal$1.apply(InMemoryRequestJournal.java:57)
com.google.common.collect.Iterators$7.computeNext(Iterators.java:652)
com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143)
com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138)
com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:268)
com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:226)
com.github.tomakehurst.wiremock.verification.InMemoryRequestJournal.getRequestsMatching(InMemoryRequestJournal.java:53)
com.github.tomakehurst.wiremock.core.WireMockApp.findRequestsMatching(WireMockApp.java:167)
com.github.tomakehurst.wiremock.admin.FindRequestsTask.execute(FindRequestsTask.java:35)
com.github.tomakehurst.wiremock.http.AdminRequestHandler.handleRequest(AdminRequestHandler.java:55)
com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:38)
com.github.tomakehurst.wiremock.jetty6.Jetty6HandlerDispatchingServlet.service(Jetty6HandlerDispatchingServlet.java:98)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
Can you post the code that triggered the problem? Hard to infer what happened from just a stack trace.
Sure, here is the client request. I if remove the withQueryParam clause it will execute without errors.
List<LoggedRequest> requests = WireMock.findAll(postRequestedFor(urlPathEqualTo(BASE_SEND_PATH))
.withRequestBody(matching(".*\"FORGOT_PASSWORD\".*"))
.withQueryParam("pid", equalTo(pid)));
Thanks for sharing. Apologies I haven't had time to replicate yet!
The NPE bug was actually fixed in 1.56. Have either of you seen a recurrence of this since then?
We ran in to the same problem. When trying to find a near match, WireMock.verificationExceptionForNearMisses uses the static findNearMissesFor, which tries to talk to a WireMock server via http instead of using the Admin instance for the JUnit rule. Changing it to use findAllNearMissesFor like verifyThat does solves it.
Preparing a PR.
@reftel Thanks for the commit! Just ran into your issue myself. Could you please make a PR? I hope @tomakehurst can look it and merge. It's quite an annoying bug.
I had the same problem, and I solved it just adding an older mvn dependency to my pom the version 1.57 to be precisely. Hope that helps!
I debugged and in my case the response coming back from the wiremock server was java.lang.NoClassDefFoundError: javax/servlet/http/HttpUpgradeHandler. I added the servlet 3.1 API to our test dependencies and the problem went away: javax.servlet:javax.servlet-api:3.1.0
Most helpful comment
I debugged and in my case the response coming back from the wiremock server was
java.lang.NoClassDefFoundError: javax/servlet/http/HttpUpgradeHandler. I added the servlet 3.1 API to our test dependencies and the problem went away:javax.servlet:javax.servlet-api:3.1.0