web-dev-qa-db-fra.com

Obtenir "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" lors de l'exécution du test dans IntelliJ 10.5

J'utilise JUnit-dep 4.10 et Hamcrest 1.3.RC2.

J'ai créé un matcher personnalisé qui ressemble à ce qui suit:

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 */
    }
}

Cela fonctionne parfaitement bien lorsqu'il est exécuté à partir de la ligne de commande en utilisant Ant. Mais lorsqu'il est exécuté à partir d'IntelliJ, il échoue avec:

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)

Mon hypothèse est qu'il utilise le mauvais hamcrest.MatcherAssert. Comment puis-je trouver le fichier hamcrest.MatcherAssert utilisé (c'est-à-dire le fichier JAR utilisé pour hamcrest.MatcherAssert)? AFAICT, le seul bocal hamcrest de mon classpath est 1.3.RC2.

IntelliJ IDEA utilise-t-il sa propre copie de JUnit ou de Hamcrest?

Comment sortir le runtime CLASSPATH qu'IntelliJ utilise?

208
November Yankee

Le problème était que la mauvaise classe hamcrest.Matcher, et non pas hamcrest.MatcherAssert, était utilisée. C’était une dépendance de Junit-4.8 qu’une de mes dépendances spécifiait.

Pour voir quelles dépendances (et versions) sont incluses à partir de quelle source lors du test, exécutez:

mvn dependency:tree -Dscope=test
55
November Yankee

Assurez-vous que le hamcrest jar est plus élevé dans l’ordre d’importation que votre JUnit jar.

JUnit est livré avec sa propre classe org.hamcrest.Matcher qui est probablement utilisée à la place.

Vous pouvez également télécharger et utiliser junit-dep-4.10.jar à la place qui est JUnit sans les classes hamcrest.

mockito contient également les classes de hamcrest, vous devrez donc probablement le déplacer et le réorganiser.

256
Garrett Hall

Ce problème se pose également lorsque vous avez mockito-all sur votre chemin de classe, qui est déjà obsolète.

Si possible, incluez simplement mockito-core .

Maven config pour mélanger le junit, le mockito et le 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>
155
Tom Parkinson

Ce qui suit devrait être le plus correct aujourd'hui. Notez que junit 4.11 dépend de hamcrest-core, vous ne devriez donc pas avoir besoin de spécifier que mockito-all ne peut pas être utilisé car il inclut (ne dépend pas) de 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>
26
Ulf Lindback

Cela a fonctionné pour moi après avoir lutté un peu

<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>
13
Raul

Malgré le fait qu'il s'agisse d'une question très ancienne Et que nombre des idées susmentionnées ont probablement résolu de nombreux problèmes, Je souhaite toujours partager la solution avec la communauté qui a résolu mon problème.

J'ai constaté que le problème était une fonction appelée "hasItem" Que j'utilisais pour vérifier si un tableau JSON contient un élément spécifique . Dans mon cas, j'ai recherché une valeur de type Long.

Et cela a conduit au problème.

D'une manière ou d'une autre, les Matchers ont des problèmes avec les valeurs de type Long ..__ (je n'utilise pas tellement JUnit ou Rest-Assured, idk. Exactement pourquoi, )

Donc, ce que j'ai fait pour résoudre le problème était le suivant ... au lieu d'utiliser:

long ID = ...;

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

vous devez juste transtyper vers Integer . Le code de travail ressemblait à ceci:

long ID = ...;

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

Ce n’est probablement pas la meilleure solution, Mais je voulais simplement mentionner que l’exception peut également être levée à cause de types de données incorrects ou inconnus.

1
Siro

J'ai un projet Gradle et quand ma section de dépendances build.gradle ressemble à ceci:

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'
}

cela mène à cette 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)

pour résoudre ce problème, j'ai remplacé "mockito-all" par "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'
}

L'explication entre mockito-all et mockito-core peut être trouvée ici: https://solidsoft.wordpress.com/2012/09/11/beyond-the-mockito- refcard-part-3-mockito-core-vs-mockito-tout-dans-les-projets-basés-mavengradle/

en plus de Mockito, mockito-all.jar contient également (à partir de 1.9.5) deux dépendances: Hamcrest et Objenesis (omettons un instant ASM reconditionné et CGLIB pour un moment). La raison en était d’avoir tout ce dont on a besoin dans un JAR pour le mettre sur un classpath. Cela peut sembler étrange. mais souvenez-vous que le développement de Mockito a commencé à une époque où pure Ant (sans gestion de la dépendance) était la version la plus populaire système pour les projets Java et tous les fichiers JAR externes requis par un projet (c’est-à-dire les dépendances de notre projet et leurs dépendances) avaient être téléchargé manuellement et spécifié dans un script de construction.

D'autre part, mockito-core.jar n'est que des classes Mockito (également avec ASM et CGLIB reconditionnés). Lorsque vous l'utilisez avec Maven ou Gradle requis les dépendances (Hamcrest et Objenesis) sont gérées par ces outils (téléchargé automatiquement et mis sur un classpath de test). Ça permet de écrasez les versions utilisées (par exemple, si nos projets n'utilisent jamais, mais version rétrocompatible), mais le plus important est celles-ci les dépendances ne sont pas cachées dans mockito-all.jar, ce qui permet de détecté une incompatibilité de version possible avec l'analyse de dépendance outils. C'est une bien meilleure solution lorsque l'outil géré par dépendance est utilisé dans un projet.

0
Pavel

Cela a fonctionné pour moi. Pas besoin d'exclure quoi que ce soit. Je viens d'utiliser mockito-core à la place 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'
0
Joni Lappalainen

Dans mon cas, j'ai dû exclure un hamcrest plus ancien de 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>
0
André

Je sais que ce n'est pas la meilleure solution, mais si vous ne parvenez pas à faire fonctionner le classpath, il s'agit d'une solution de plan B.

Dans mon chemin de classe de test, j'ai ajouté l'interface suivante avec une implémentation par défaut pour la méthode describeMismatch.

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_();
}
0
Francis

Ce qui a fonctionné pour moi a été d’exclure le groupe hamcrest de la compilation du test Junit.

Voici le code de mon build.gradle:

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

Si vous utilisez IntelliJ, vous devrez peut-être exécuter gradle cleanIdea idea clean build pour détecter à nouveau les dépendances. 

0
Jason D