Monday, August 5, 2013

java.lang.NoClassDefFoundError: org/hamcrest/TypeSafeMatcher exception using maven and jmock



Running Ctrl+F11 on the test class to issue JUnit test, you get:

java.lang.NoClassDefFoundError: org/hamcrest/TypeSafeMatcher
  at java.lang.ClassLoader.defineClass1(Native Method)
  ...






This exception may be thrown when running the JUnit test using eclipse (Ctrl+F11 having the test class active).
More than just one cause is possible.

Here, I'm gonna show a consistent debug use case to discover and solve the problems, step by step.

First step is to make sure if the application has a successful build, because sometimes you get it although not having a successful result in the JUnit test via eclipse (below you'll see).

The "build" may be issued using:

- the prompt ("mvn build", "mvn install" or "mvn install -U"), under the PROJECT_ROOT.
or
- eclipse: Ctrl+F11 on the pom.xml file to run "mvn install" command.


Using eclipse:





This test also fails:

Tests in error: 
  testSayGreeting(br.com.adr.rin157.GreetingTest): org/hamcrest/TypeSafeMatcher
  testJmock(br.com.adr.rin160.TestClass3): org/jmock/internal/matcher/MethodMatcher





Then, let's fix the build first, and after we check the JUnit test - it is a two-phase checking.

Reading the exception thrown, the problem is about the "hamcrest" library.
Let's check all the "hamcrest" dependencies, removing all them.
Then check which one is really necessary.

This is simple, a necessary library causes messages of unknown classes by the eclipse's on-the-fly compiler.
Let just the necessary libraries, and try switching the alternatives, adding and testing each one, one by its turn.
When the on-the-fly compilation runs without errors or messages, the new configuration is set correctly.

In this example, it was the hamcrast's source declaration which was causing the problem.
After the test described above, the conflicting dependency was found and removed, shown below.

  <dependency>
    <groupId>hamcrest_260_local</groupId>
    <artifactId> core</artifactId>
    <version> sources</version>
    <type>jar</type>
  </dependency>





After that, a new final "mvn install test" to confirm, which shall be successful:






I got some information on the Internet that the order of the dependencies could be the cause of the problem.
You may also test it.
In this example, the tests demonstrated that the order was irrelevant.
Check the following two pictures below.








After a successful build, the JUnit test is checked again, issuing the command referred above.
Unfortunately, there is yet another issue to solve.
The exception returned is:

java.lang.SecurityException: class "org.hamcrest.TypeSafeMatcher"'s signer information does not match signer information of other classes in the same package
  at java.lang.ClassLoader.checkCerts(Unknown Source)
  ...



The trick for the solution is inside is the "Run configurations..." setting.
Go to:






The wrong configuration - classpath after project:






The right configuration - classpath before project:






To set the right configuration, inverting project vs. classpath order, do:

1. Select the project entry and click the "Remove" button.
2. select "User entries", then "Add Projects"


Follow by blue highlighted buttons in the picture:











Then run:
























That's it. : )


NOTES

You can check by your own -  the code is here .

The test was created as follows:

1. Eclipse Juno, but any version fits.

2. The code used here you find at http://www.askeygeek.com/jmock-for-beginners/

3. The library is jmock-2.6.0 downloaded from the jMock site and installed at a local maven repository.

Alternatively, you may use the following dependencies from Maven Repository, or use the pom.xml file inside the code :

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>

<!--jMock 2 Core -->
<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock</artifactId>
<version>2.6.0</version>
</dependency>

<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
</dependency>

<dependency>
<groupId>org.beanshell</groupId>
<artifactId>bsh-core</artifactId>
<version>2.0b4</version>
</dependency>

<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>1.0</version>
</dependency>

<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.0</version>
</dependency>

<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-junit3</artifactId>
<version>2.6.0</version>
</dependency>

<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-junit4</artifactId>
<version>2.6.0</version>
</dependency>

<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-script</artifactId>
<version>2.6.0</version>
</dependency>

<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-legacy</artifactId>
<version>2.6.0</version>
</dependency>






No comments:

Post a Comment

eclipse: java: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" or Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder

  >PROBLEM Using Eclipse, you try to run a simple logging test using "org.slf4j.Logger" like the sample below: package Test; im...