Getting "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" when running test in IntelliJ 10.5
Asked Answered
B

15

245

I'm using JUnit-dep 4.10 and Hamcrest 1.3.RC2.

I've created a custom matcher that looks like the following:

public static class MyMatcher extends TypeSafeMatcher<String> {
    @Override
    protected boolean matchesSafely(String s) {
        /* implementation */
    }

    @Override
    public void describeTo(Description description) {
        /* implementation */
    }

    @Override
    protected void describeMismatchSafely(String item, Description mismatchDescription) {

        /* implementation */
    }
}

It works perfectly fine when run from the command line using Ant. But when run from IntelliJ, it fails with:

java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:18)
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8)
    at com.netflix.build.MyTest.testmyStuff(MyTest.java:40)

My guess is that it's using the wrong hamcrest.MatcherAssert. How do I find which hamcrest.MatcherAssert it's using (ie which jar file it's using for hamcrest.MatcherAssert)? AFAICT, the only hamcrest jars in my classpath is 1.3.RC2.

Is IntelliJ IDEA using it's own copy of JUnit or Hamcrest?

How do I output the runtime CLASSPATH that IntelliJ is using?

Briannabrianne answered 23/10, 2011 at 22:29 Comment(0)
B
63

The problem was that the wrong hamcrest.Matcher, not hamcrest.MatcherAssert, class was being used. That was being pulled in from a junit-4.8 dependency one of my dependencies was specifying.

To see what dependencies (and versions) are included from what source while testing, run:

mvn dependency:tree -Dscope=test
Briannabrianne answered 24/10, 2011 at 21:48 Comment(5)
I had the same issue. I was using JUnit-dep and Hamcrest-core but I had Powermock listed earlier in the pom which was resulting in JUnit being included before JUnit-dep and Hamcrest.Photoperiod
Also mockito-all includes some Hamcrest classes. It's better to use mockito-core and exclude the hamcrest dependency.Yann
Just stumbled upon the exact same problem. Solution was upping junit version to 4.11 which is compatible (i.e. "contains classes from") with hamcrest 1.3Commentative
For those where all the suggestions did not work as well (Dependency order, exlusions, removing replace -all with -core, etc...): I had to change hamcrest back to version 1.1 and now everything works again.Tabbitha
for me it worked when I changed my import to import static org.mockito.Matchers.anyString; from import static org.mockito.ArgumentMatchers.anyString;Golden
C
281

Make sure the hamcrest jar is higher on the import order than your JUnit jar.

JUnit comes with its own org.hamcrest.Matcher class that is probably being used instead.

You can also download and use the junit-dep-4.10.jar instead which is JUnit without the hamcrest classes.

mockito also has the hamcrest classes in it as well, so you may need to move\reorder it as well

Claudetteclaudia answered 24/10, 2011 at 15:47 Comment(12)
OP said they were already using the '-dep-' jar. But your guess that it's using the Matcher class from the JUnit jar sounds right. So it's probably that the IDE is using its own copy of JUnit.Sphagnum
I removed IntelliJ's copy of junit.jar and junit-4.8.jar, installed junit-dep-4.10.jar into IntelliJ's lib/ directory, and the problem still occurs.Briannabrianne
Have you checked the .classppath to make sure there are no other JUnit entries?Claudetteclaudia
I just checked the runtime classpath as given on the first line when debugging a test. The only jar file that has MatcherAssert is hamcrest-core-1.3.Briannabrianne
Maybe using junit-dep no longer solves this: the junit:junit-dep artifact only consists of a POM pointing to junit:junit now? And for future reference, a bug report: 4.9 and 4.10 "junit" artifacts in Maven Central have hamcrest as dependency defined while in "junit" artifact the hamcrest classes are already included.Styliform
excellent man! I was facing this issue in OSGI environment...when I had Junit 4 in my dependencies...I could not see hamcrest plugin when I searched for it. However, if I removed Junit and searched...I did find it in the list.Vanden
JUnit 4.11 is compatible with Hamcrest 1.3 and JUnit 4.10 is compatible with Hamcrest 1.1 search.maven.org/remotecontent?filepath=junit/junit-dep/4.10/…Thingumajig
make sure you are NOT using mockito-all, but instead mockito-core with an exclusion of hamcrestPrimordial
It is 7:33 PM in the office an I am working on an important feature that I must deliver before go out in a Vacation and It is Friday, I am in that Vacation next week !!!!!! How da hell I could get this error now !!!Deciare
"higher on the import" what do you mean ?Deciare
This applies to Eclipse too.Monopolize
I've got the same clash withJUnit 4.11 and Hamcrest 2.0.0.0.Spathic
B
179

This problem also arises when you have mockito-all on your class path, which is already deprecated.

If possible just include mockito-core.

Maven config for mixing junit, mockito and hamcrest:

<dependencies>
  <dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>1.3</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <version>1.3</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
</dependencies>
Bagger answered 24/5, 2013 at 12:49 Comment(6)
This is exactly the hint I needed. The idea simply is to check all this über jars for hidden dependencies. Or better not to be lazy and don't use them at all.Libelee
Quite as the new versions of mockito include hamcrest also same with powermock!Bagger
Should that be mockito-core instead of mockito-all?Exorbitant
You could include just core if you only need it in pace of all however the above should work in all cases. The order of the dependencies is the important bit mvn 3 starts from the top in order of priority.Bagger
You should NOT include mockito-all since that includes hamcrest 1.1, instead include mockito-core and exclude hancrest from it (which you cannot do from all)Primordial
"If possible just include mockito-core.". OK, so then why does this answer still use mockito-all ?Laflamme
B
63

The problem was that the wrong hamcrest.Matcher, not hamcrest.MatcherAssert, class was being used. That was being pulled in from a junit-4.8 dependency one of my dependencies was specifying.

To see what dependencies (and versions) are included from what source while testing, run:

mvn dependency:tree -Dscope=test
Briannabrianne answered 24/10, 2011 at 21:48 Comment(5)
I had the same issue. I was using JUnit-dep and Hamcrest-core but I had Powermock listed earlier in the pom which was resulting in JUnit being included before JUnit-dep and Hamcrest.Photoperiod
Also mockito-all includes some Hamcrest classes. It's better to use mockito-core and exclude the hamcrest dependency.Yann
Just stumbled upon the exact same problem. Solution was upping junit version to 4.11 which is compatible (i.e. "contains classes from") with hamcrest 1.3Commentative
For those where all the suggestions did not work as well (Dependency order, exlusions, removing replace -all with -core, etc...): I had to change hamcrest back to version 1.1 and now everything works again.Tabbitha
for me it worked when I changed my import to import static org.mockito.Matchers.anyString; from import static org.mockito.ArgumentMatchers.anyString;Golden
P
29

The following should be the most correct today. Note, junit 4.11 depends on hamcrest-core, so you shouldn't need to specify that at all, mockito-all cannot be used since it includes (not depends on) hamcrest 1.1

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.10.8</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
Primordial answered 21/11, 2014 at 10:17 Comment(2)
Note that JUnit 4.12 now depends on hamcrest-core 1.3.Bod
Exclusion from mockito-all helped to me, not mockito-core. Also declaring Hamcrest before Mockito in pom.xml works.Regicide
S
17

This worked for me after struggling a bit

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

 <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
 </dependency>

 <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
 </dependency>
Shaeffer answered 12/4, 2014 at 20:13 Comment(1)
Same for me. Putting dependencies in this order helps maven to resolve transitive deps correctly. Explicitely excluding hamcrest from mockito-core or mockito-all might be safer though, in case someone reorders deps in your pom.Ahmad
B
5

I know this is an old thread but what solved the issue for me was adding the following to my build.gradle files. As already stated above there is a compatibility issue with mockito-all

Possibly useful post:

testCompile ('junit:junit:4.12') {
    exclude group: 'org.hamcrest'
}
testCompile ('org.mockito:mockito-core:1.10.19') {
    exclude group: 'org.hamcrest'
}
testCompile 'org.hamcrest:hamcrest-core:1.3'
Byssus answered 22/5, 2017 at 6:11 Comment(0)
P
4

Try

expect(new ThrowableMessageMatcher(new StringContains(message)))

instead of

expectMessage(message)

You may write a custom ExpectedException or utility method to wrap up the code.

Polarization answered 5/2, 2015 at 23:14 Comment(0)
P
2

I have a gradle project and when my build.gradle dependencies section looks like this:

dependencies {
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'

    testImplementation group: 'org.mockito', name: 'mockito-all', version: '1.10.19'
    testImplementation 'junit:junit:4.12'
//    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.23.4'

    compileOnly 'org.projectlombok:lombok:1.18.4'
    apt 'org.projectlombok:lombok:1.18.4'
}

it leads to this exception:

java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V

    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:18)
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8)

to fix this issue, I've substituted "mockito-all" with "mockito-core".

dependencies {
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'

//    testImplementation group: 'org.mockito', name: 'mockito-all', version: '1.10.19'
    testImplementation 'junit:junit:4.12'
    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.23.4'

    compileOnly 'org.projectlombok:lombok:1.18.4'
    apt 'org.projectlombok:lombok:1.18.4'
}

The explanation between mockito-all and mockito-core can be found here: https://solidsoft.wordpress.com/2012/09/11/beyond-the-mockito-refcard-part-3-mockito-core-vs-mockito-all-in-mavengradle-based-projects/

mockito-all.jar besides Mockito itself contains also (as of 1.9.5) two dependencies: Hamcrest and Objenesis (let’s omit repackaged ASM and CGLIB for a moment). The reason was to have everything what is needed inside an one JAR to just put it on a classpath. It can look strange, but please remember than Mockito development started in times when pure Ant (without dependency management) was the most popular build system for Java projects and the all external JARs required by a project (i.e. our project’s dependencies and their dependencies) had to be downloaded manually and specified in a build script.

On the other hand mockito-core.jar is just Mockito classes (also with repackaged ASM and CGLIB). When using it with Maven or Gradle required dependencies (Hamcrest and Objenesis) are managed by those tools (downloaded automatically and put on a test classpath). It allows to override used versions (for example if our projects uses never, but backward compatible version), but what is more important those dependencies are not hidden inside mockito-all.jar what allows to detected possible version incompatibility with dependency analyze tools. This is much better solution when dependency managed tool is used in a project.

Pascale answered 6/1, 2019 at 20:9 Comment(0)
B
2

As of July, 2020 the following dependencies in pom.xml worked for me:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest</artifactId>
    <version>2.1</version>
</dependency>

With this 4.13 junit library and hamcrest, it uses hamcrest.MatcherAssert when asserting and throws exception- enter image description here

Bookplate answered 6/7, 2020 at 17:34 Comment(0)
C
1

Despite the fact that this is a very old question and probably many of the beforementioned ideas solved many problems, I still want to share the solution with the community that fixed my problem.

I found that the problem was a function called "hasItem" which I was using to check whether or not a JSON-Array contains a specific item. In my case I checked for a value of type Long.

And this led to the problem.

Somehow, the Matchers have problems with values of type Long. (I do not use JUnit or Rest-Assured so much so idk. exactly why, but I guess that the returned JSON-data does just contain Integers.)

So what I did to actually fix the problem was the following. Instead of using:

long ID = ...;

...
.then().assertThat()
  .body("myArray", hasItem(ID));

you just have to cast to Integer. So the working code looked like this:

long ID = ...;

...
.then().assertThat()
  .body("myArray", hasItem((int) ID));

That's probably not the best solution, but I just wanted to mention that the exception can also be thrown because of wrong/unknown data types.

Chor answered 27/11, 2017 at 23:0 Comment(0)
W
1

In my case, I had to exclude an older hamcrest from junit-vintage:

<dependency>
  <groupId>org.junit.vintage</groupId>
  <artifactId>junit-vintage-engine</artifactId>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest-core</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.hamcrest</groupId>
  <artifactId>hamcrest</artifactId>
  <version>2.1</version>
  <scope>test</scope>
</dependency>
Wendt answered 9/2, 2019 at 12:38 Comment(0)
C
1

This worked for me. No need to exclude anything. I just used mockito-core instead mockito-all

testCompile 'junit:junit:4.12'
testCompile group: 'org.mockito', name: 'mockito-core', version: '3.0.0'
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '2.1'
Cloison answered 14/8, 2019 at 10:57 Comment(0)
A
0

What worked for me was excluding the hamcrest group from the junit test compile.

Here is the code from my build.gradle:

testCompile ('junit:junit:4.11') {
    exclude group: 'org.hamcrest'
}

If you're running IntelliJ you may need to run gradle cleanIdea idea clean build to detect the dependencies again.

Amal answered 10/5, 2016 at 17:48 Comment(0)
O
0

I know that's not the best answer, but if you can't get the classpath working, this is a plan B solution.

In my test classpath, I added the following interface with a default implementation for the describeMismatch method.

package org.hamcrest;

/**
 * PATCH because there's something wrong with the classpath. Hamcrest should be higher than Mockito so that the BaseMatcher
 * implements the describeMismatch method, but it doesn't work for me. 
 */
public interface Matcher<T> extends SelfDescribing {

    boolean matches(Object item);

    default void describeMismatch(Object item, Description mismatchDescription) {
        mismatchDescription.appendDescriptionOf(this).appendValue(item);
    }

    @Deprecated
    void _dont_implement_Matcher___instead_extend_BaseMatcher_();
}
Oligosaccharide answered 30/5, 2016 at 13:20 Comment(0)
P
0

For jUnit 4.12, the following dependency combination fixed my issue.

<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.hamcrest</groupId>
   <artifactId>hamcrest-core</artifactId>
   <version>1.3</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.hamcrest</groupId>
   <artifactId>hamcrest-library</artifactId>
   <version>1.3</version>
   <scope>test</scope>
</dependency>
Polson answered 30/3, 2021 at 13:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.