web-dev-qa-db-fra.com

NoSuchMethodError avec Hamcrest 1.3 & JUnit 4.11

Une autre instance de NoSuchMethodError pour la combinaison JUnit & Hamcrest . Code incriminé:

assertThat(dirReader.document(0).getFields(), hasItem(
    new FeatureMatcher<IndexableField, String>(equalTo("Patisnummer"), "Field key", "Field key") {
        @Override
        protected String featureValueOf(IndexableField actual) {
            return actual.name();
        } } ));

Lignes commentées 152–157 dans IndexerTest.Java (commit ac72ce )

Provoque une erreur NoSuchMethodError (voir http://db.tt/qkkkTE78 pour une sortie complète):

Java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V
at org.hamcrest.FeatureMatcher.matchesSafely(FeatureMatcher.Java:43)
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.Java:55)
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.Java:25)
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.Java:14)
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.Java:55)
at org.junit.Assert.assertThat(Assert.Java:770)
at org.junit.Assert.assertThat(Assert.Java:736)
at indexer.IndexerTest.testIndexContainsField(IndexerTest.Java:152)

La mise en place:

  • JUnit 4.11
  • Hamcrest 1.3
  • Utilisation du plugin Mafen's surefire (version 2.14), qui utilise son JUnitCoreProvider
  • Java 7 (OpenJDK)
  • Voir pom (commit ac72ce )

Contexte:

Un NoSuchMethodError est provoqué par des classes (compilées) qui appellent des méthodes non existantes. Le cas spécifique de describeMismatch et de la combinaison JUnit + Hamcrest est souvent dû à une incompatibilité entre les classes Hamcrest incluses dans JUnit et les versions de ces classes dans la bibliothèque Hamcrest.

Tentatives pour résoudre l'erreur NoSuchMethodError:

  • Le pom contient une dépendance explicite sur Hamcrest-library 1.3, Hamcrest-core 1.3 et JUnit 4.11 (dans cet ordre) comme suggéré par Garrett Hall dans answer to Obtention de "NoSuchMethodError: org. hamcrest.Matcher.describeMismatch "lors de l'exécution du test dans IntelliJ 10.5

  • Selon la documentation JUnit, la dépendance JUnit 4.11 Maven n'inclut plus les classes Hamcrest compilées, mais dépend plutôt de Hamcrest-core 1.3; donc la NoSuchMethodError ne devrait pas se produire.

  • Vérifier l'arbre de dépendance avec mvn dependency:tree comme suggéré par Dan in réponse à déclaration junit et hamcrest montre les dépendances explicites sur Hamcrest 1.3 et JUnit 4.11 et aucune autre dépendance à ces fichiers (voir http://db.tt/C2OfTDJB pour la sortie complète).

  • Dans un autre test, la variable NoSuchMethodError a été évitée en utilisant:

    assertThat(
        "Zylab detector not available",
        d.getDetectors(),
        hasItem(Matchers.<Detector>instanceOf(ZylabMetadataXmlDetector.class)));
    

    Dans les lignes 120 à 123 de IndexerTest.Java (commit ac72ce ) Au lieu du plus évident:

    assertThat(
        "Zylab detector not available",
        d.getDetectors(),
        hasItem(isA(ZylabMetadataDetector.class));
    

    Je ne sais pas si le paramètre de type explicite <Detector>, utilisant instanceOf au lieu de isA, la référence explicite à la variable Matchers de Hamcrest, ou une combinaison de ceux évitant la variable NoSuchMethodException; après avoir bidouillé et essayé différentes choses, cela a fonctionné.

  • L'utilisation de paramètres de type explicite n'a pas résolu/évité l'erreur.

  • L'utilisation d'une classe dérivée de BaseMatcher au lieu de FeatureMatcher n'a pas résolu/évité l'erreur.

Idées comment corriger la NoSuchMethodError?

40

Ce blog m'a aidé à résoudre le même problème:

https://tedvinke.wordpress.com/2013/12/17/mixing-junit-hamcrest-and-mockito-explaining-nosuchmethoderror/

Dans les dépendances de Mockito et Junit, ajoute l'auteur, exclut:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <exclusions>
        <exclusion>
            <artifactId>hamcrest-core</artifactId>
            <groupId>org.hamcrest</groupId>
        </exclusion>
    </exclusions>
</dependency>
23
Fred

Utilisation de David's tip et Comment diviser une chaîne sur un délimiteur dans Bash? a abouti au script bash suivant:

( IFS=":"; for i in `mvn dependency:build-classpath | grep -v '\[INFO\]'`; do jar tf $i | awk "{print \"$i\\t\" \$1}"; done | grep Matcher )

(en ligne à http://www.kaspervandenberg.net/2013/scripts/findDependencyClass.sh )

Ce qui a révélé que la dépendance JGlobus-Core-2.0.4 avait ses propres versions de org.hamcrest.BaseMatcher, org.hamcrest.CoreMatchers et org.hamcrest.Matcher.

2

Ce qui a fonctionné pour moi a été de réorganiser les dépendances… Au lieu de mockito, junit,… je devais mettre Junit, mockito.

Mockito 1.9.5 utilise hamcrest 1.1, qui est incompatible et pose des problèmes.

2
Arkady O

Peut-être que l'un de ces autres fichiers JAR contient d'anciennes versions de Matcher ou BaseMatcher de Hamcrest. Voici une liste de JAR qui inclut ce dernier, bien que je n’aie aucune idée de la complexité de ce site. Existe-t-il un plugin Maven qui vous montrera toutes les dépendances qui incluent une classe similaire à l’arbre de dépendance?

2
David Harkness

Si vous utilisez Eclipse, l'outil "Ouvrir le type" (CTRL + SHIFT + T) peut vous aider à trouver le paquet problématique. Il suffit de rechercher le nom de la classe (par exemple, Description), les occurrences multiples de la même classe provenant de différents JAR sont des drapeaux rouges.

2
izilotti

Si vous utilisez Eclipse: Pour moi, dans Eclipse-> propriétés du projet-> chemin de construction Java Déplacer le fichier mockito-all-1.9.5.jar au bas de la liste "Ordre et exportation" . Juste au-dessus, j'ai junit-4.11.jar et au-dessus de hamcrest-core-1.3.jar

0
mrxjn

J'ai résolu ce problème jar hell dans mon projet Gradle avec le code ci-dessous:

    testCompile (group: 'junit', name: 'junit', version: '4+') {
        exclude group: 'org.hamcrest'
    }
    testCompile ('org.mockito:mockito-core:1+') {
        exclude group: 'org.hamcrest'
    }
    testCompile 'org.hamcrest:Java-hamcrest:2.0.0.0'
0

Pour un projet avec Gradle comme outil de construction:

testCompile("junit:junit:4.11") {
     exclude group: 'org.hamcrest', module: 'hamcrest-core'
     exclude group: 'org.hamcrest', module: 'hamcrest-library' 
}
testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3'
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
0
Arpit