github twitter linkedin rss
Spring Cloud and Wiremock
2016-12-23

I tried to write a test using Wiremock 2.4.1 in a Spring Boot 1.4.3 with Spring Cloud Camden.SR3 project.

When using the WireMockRule you get exceptions like:

java.lang.NoClassDefFoundError: org/apache/http/HttpRequest
  at com.github.tomakehurst.wiremock.core.WireMockApp.buildStubRequestHandler(WireMockApp.java:124)
  at com.github.tomakehurst.wiremock.WireMockServer.<init>(WireMockServer.java:71)
  at com.github.tomakehurst.wiremock.junit.WireMockRule.<init>(WireMockRule.java:42)
  at com.github.tomakehurst.wiremock.junit.WireMockRule.<init>(WireMockRule.java:38)
  at com.github.tomakehurst.wiremock.junit.WireMockRule.<init>(WireMockRule.java:47)
  at com.example.Foo.<init>(Foo.java:8)
  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
  at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217)
  at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
  at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
  at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
  at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.ClassNotFoundException: org.apache.http.HttpRequest
  at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
  ... 32 more

Somehow, after adding the POM import on Spring Cloud, something breaks. If you compare the output of mvn dependency:tree, you’ll notice the following dependencies disappear:

+- org.eclipse.jetty:jetty-server:jar:9.3.14.v20161028:test
|  +- javax.servlet:javax.servlet-api:jar:3.1.0:test
|  +- org.eclipse.jetty:jetty-http:jar:9.3.14.v20161028:test
|  \- org.eclipse.jetty:jetty-io:jar:9.3.14.v20161028:test
+- org.eclipse.jetty:jetty-servlet:jar:9.3.14.v20161028:test
|  \- org.eclipse.jetty:jetty-security:jar:9.3.14.v20161028:test
+- org.eclipse.jetty:jetty-servlets:jar:9.3.14.v20161028:test
|  +- org.eclipse.jetty:jetty-continuation:jar:9.3.14.v20161028:test
|  \- org.eclipse.jetty:jetty-util:jar:9.3.14.v20161028:test
+- org.eclipse.jetty:jetty-webapp:jar:9.3.14.v20161028:test
|  \- org.eclipse.jetty:jetty-xml:jar:9.3.14.v20161028:test
+- org.apache.httpcomponents:httpclient:jar:4.5.2:test
|  +- org.apache.httpcomponents:httpcore:jar:4.4.5:test
|  \- commons-codec:commons-codec:jar:1.10:test
+- net.sf.jopt-simple:jopt-simple:jar:4.9:test

After some searching the web, I found this.

The Spring Cloud Release Train BOM imports spring-cloud-contract-dependencies which in turn has exclusions for the dependencies needed by WireMock. This might lead to a situation that even if you’re not using Spring Cloud Contract then your dependencies will be influenced anyways.

Apparently the correct way to combine WireMock and Spring Cloud is to use the Spring Cloud Contract. Bad thing is, your files captured with the current version of WireMock (2.4.1) won’t work, because the Spring Cloud Contract uses WireMock 2.1.7.

So either you use WireMock 2.1.7 (Download here) to capture your files or you override the WireMock version in your project, by adding this in your pom.xml:

<dependencyManagement>
  <dependencies>
    <dependency>
    <groupId>com.github.tomakehurst</groupId>
    <artifactId>wiremock</artifactId>
    <version>2.4.1</version>
    </dependency>
  </dependencies>
</dependencyManagement>

Now it’s running with WireMock 2.4.1. Happy mocking.


Back to posts