Wiremock: "java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing" when importing wiremock 2.7.1 maven dependency

Created on 30 Aug 2017  路  9Comments  路  Source: tomakehurst/wiremock

Greetings,

After some research I decided to use wiremock in our project unit tests, which were working and running as expected before including wiremock 2.7.1 in the project's pom.xml

my current test scope dependencies until now were the following (taken from the project's BOM file)

    <!-- testing dependency versions -->
    <junit.version>4.12</junit.version>
    <assertj.version>3.4.0</assertj.version>
    <equalsverifier.version>2.1.7</equalsverifier.version>
    <openpojo.version>0.8.4</openpojo.version>

after including wiremock in the pom.xml file:

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

all tests ceased to work, no matter which tool I tried to use

  • Eclipse Oxygen Release (4.7.0)
  • terminal mvn clean test

the following exception is being thrown:

java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:70)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassNotFoundException: org.hamcrest.SelfDescribing
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 24 more

After inspecting the pom.xml file in wiremock 2.7.1 I think to have found the possible cause of this:

  • Wiremock is including it's own JUnit library, which luckily matches the version I'm using but with the subtle difference that it is excluding hamcrest-core:
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>hamcrest-core</artifactId>
          <groupId>org.hamcrest</groupId>
        </exclusion>
      </exclusions>
    </dependency>

Questions

  • Why is wiremock delivering its own JUnit dependency in a <scope>compile</scope> scope?
  • And why is hamcrest-core being implicitly excluded from it?

The real question

  • How to workaround this?

I'm considering to exclude the junit dependency from my wiremock dependency, but not yet sure what side effects may arise from this.

Any pointers in the right direction are greatly welcome!

Thank you very much in advance.

PS: Removing the wiremock dependency fixes the problem for me. With the obvious downside that then I cannot use it :)

Most helpful comment

JUnit is now an compileOnly/provided dependency and excluded from the standalone JAR in 2.25.0. Hopefully that should resolve this issue.

All 9 comments

Excluding junit from wiremock dependency fixes the issue for me:

    <dependency>
      <groupId>com.github.tomakehurst</groupId>
      <artifactId>wiremock</artifactId>
      <version>2.7.1</version>
      <exclusions>
        <exclusion>
          <artifactId>junit</artifactId>
          <groupId>junit</groupId>
        </exclusion>
      </exclusions>
    </dependency>

But I'm not sure if any side effects may come from this. Until now all seems to be working as expected.

OK, I'm going to close this off.

WireMock has a compile-time dependency on JUnit because it depends directly on some JUnit classes. It excludes hamcrest from the compile scope because it doesn't need it there.

I'm not sure what could be done to improve on this within WireMock that would satisfy everyone and avoid breaking backwards compatibility. Maybe one for v3.

It excludes hamcrest from the compile scope because it doesn't need it there.

That's excellent news actually :) because it answers my concern about side effects due to some unknown reason that may have led you to exclude the dependency, which is simply that you just do not use it.

That means that there is nothing wrong with including it on my side, and that could be (?) the solution for this specific problem, you could just include JUnit without further modifications.

Thank you very much for clarifying this!

BTW: Wiremock is awesome.

@tomakehurst instead of closing this issue, wouldn't it be better to tag it as a change for version 3?

This is now also a problem in JUnit 5.4 and 5.5. Previous version of JUnit 5 seemed fine though.

@PyvesB can you share the details of your setup and the error you're seeing?

@PyvesB can you share the details of your setup and the error you're seeing?

Sure. Here's the minimal example I get failures with using Maven 3.6.1.

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.github.pyvesb</groupId>
    <artifactId>jupiter-wiremock</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.tomakehurst</groupId>
            <artifactId>wiremock</artifactId>
            <version>2.24.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>
</project>

MainTest.java:

import org.junit.jupiter.api.Test;

class MainTest {
    @Test
    void test() {
        System.out.println("Test ran successfully!");
    }
}

The following error is printed in the logs when running that unique test:

Sep 01, 2019 7:21:28 PM org.junit.platform.launcher.core.DefaultLauncher handleThrowable
WARNING: TestEngine with ID 'junit-jupiter' failed to execute tests
java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at org.junit.platform.commons.util.ReflectionUtils.lambda$tryToLoadClass$9(ReflectionUtils.java:779)
    at org.junit.platform.commons.function.Try.lambda$call$0(Try.java:57)
    at org.junit.platform.commons.function.Try.of(Try.java:93)
    at org.junit.platform.commons.function.Try.call(Try.java:57)
    at org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass(ReflectionUtils.java:742)
    at org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass(ReflectionUtils.java:698)
    at org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector.createAbortedExecutionPredicate(OpenTest4JAndJUnit4AwareThrowableCollector.java:40)
    at org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector.<clinit>(OpenTest4JAndJUnit4AwareThrowableCollector.java:30)
    at org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory.createThrowableCollector(JupiterThrowableCollectorFactory.java:34)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: java.lang.ClassNotFoundException: org.hamcrest.SelfDescribing
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 36 more

When Wiremock is removed, the test passes.

Thanks, I'll take a look.

JUnit is now an compileOnly/provided dependency and excluded from the standalone JAR in 2.25.0. Hopefully that should resolve this issue.

Was this page helpful?
0 / 5 - 0 ratings