it-swarm.com.de

"NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" abrufen, wenn test in IntelliJ 10.5 ausgeführt wird

Ich verwende JUnit-dep 4.10 und Hamcrest 1.3.RC2.

Ich habe einen benutzerdefinierten Matcher erstellt, der wie folgt aussieht:

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

Es funktioniert perfekt, wenn Sie es mit Ant von der Kommandozeile aus ausführen. Wenn von IntelliJ ausgeführt, schlägt es fehl mit:

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)

Meine Vermutung ist, dass es das falsche hamcrest.MatcherAssert verwendet. Wie finde ich heraus, welcher hamcrest.MatcherAssert verwendet wird (dh welche JAR-Datei für hamcrest.MatcherAssert verwendet wird)? AFAICT, die einzigen Hamcrest-Gläser in meinem Klassenpfad sind 1.3.RC2.

Verwendet IntelliJ IDEA seine eigene Kopie von JUnit oder Hamcrest?

Wie gebe ich die Runtime CLASSPATH aus, die IntelliJ verwendet?

208
November Yankee

Das Problem war, dass die falsche Klasse hamcrest.Matcher und nicht hamcrest.MatcherAssert verwendet wurde. Das wurde aus einer junit-4.8-Abhängigkeit gezogen, die eine meiner Abhängigkeiten angab.

Um zu sehen, welche Abhängigkeiten (und Versionen) aus welcher Quelle beim Testen enthalten sind, führen Sie Folgendes aus:

mvn dependency:tree -Dscope=test
55
November Yankee

Stellen Sie sicher, dass der hamcrest jar in der Importreihenfolge höher ist als Ihr JUnit jar.

JUnit enthält eine eigene org.hamcrest.Matcher-Klasse, die wahrscheinlich stattdessen verwendet wird.

Sie können auch die Datei junit-dep-4.10.jar herunterladen, die JUnit ohne die Hamcrest-Klassen ist.

mockito enthält auch die hamcrest-Klassen, daher müssen Sie sie möglicherweise auch verschieben

256
Garrett Hall

Dieses Problem tritt auch auf, wenn Sie mockito-all in Ihrem Klassenpfad haben, der bereits veraltet ist.

Wenn möglich nur Mockito-Core einschließen.

Maven config zum Mischen von Junit, Mockito und 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

Das Folgende sollte heute das Richtige sein. Hinweis, junit 4.11 hängt vom hamcrest-core ab. Sie müssen also nicht angeben, dass mockito-all nicht verwendet werden kann, da es umfasst (nicht abhängig von) 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

Das funktionierte für mich, nachdem ich mich ein bisschen schwer getan hatte

<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

Versuchen

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

anstatt von

expectMessage(message)

Sie können eine benutzerdefinierte ExpectedException oder eine Dienstprogrammmethode schreiben, um den Code zusammenzufassen.

4
Qiang Li

Ich weiß, dass dies ein alter Thread ist, aber das Problem wurde behoben, indem ich Folgendes zu meinen build.gradle -Dateien hinzufügte. Wie bereits erwähnt, gibt es ein Kompatibilitätsproblem mit mockito-all

Möglicherweise nützlich 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'
2
Kai

Obwohl dies eine sehr alte Frage ist. Wahrscheinlich haben viele der oben genannten Ideen viele Probleme gelöst. Ich möchte immer noch die Lösung mit der Community teilen, die mein Problem gelöst hat.

Ich habe festgestellt, dass das Problem eine Funktion namens "hasItem" .__ war, mit der ich prüfte, ob ein JSON-Array ein bestimmtes Element enthält. In meinem Fall habe ich nach einem Wert vom Typ Long gesucht.

Und das führte zu dem Problem.

Irgendwie haben die Matchers Probleme mit Werten vom Typ Long . (Ich verwende JUnit oder Rest-Assured nicht so sehr, also idk. Warum genau ) Aber ich schätze, dass die zurückgegebenen JSON-Daten nur Integer enthalten. )

Also, was ich tat, um das Problem tatsächlich zu beheben, war folgendes.

long ID = ...;

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

sie müssen nur in Integer ..__ konvertieren. Der Arbeitscode sah also so aus:

long ID = ...;

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

Das ist wahrscheinlich nicht die beste Lösung, aber ich wollte nur erwähnen, dass die Ausnahme auch wegen falscher/unbekannter Datentypen ausgelöst werden kann.

1
Siro

Ich habe ein Gradle-Projekt und wenn meine build.gradle-Abhängigkeiten wie folgt aussehen:

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

es führt zu dieser Ausnahme:

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)

um dieses Problem zu beheben, habe ich "Mockito-All" durch "Mockito-Core" ersetzt.

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

Die Erklärung zwischen mockito-all und mockito-core finden Sie hier: https://solidsoft.wordpress.com/2012/09/11/beyond-the-mockito- refcard-part-3-mockito-core-vs-mockito-all-in-mavengradle-basierte projekte/

mockito-all.jar enthält neben Mockito selbst (ab 1.9.5) auch zwei Abhängigkeiten: Hamcrest und Objenesis (lassen Sie ASM und CGLIB für einen Moment neu einpacken). Der Grund war, alles zu haben, was benötigt wird in einem Ein-JAR, um es einfach auf einen Klassenpfad zu setzen. Es kann seltsam aussehen, Aber bitte denkt daran, dass die Entwicklung von Mockito in Zeiten begann, als pure Ant (ohne Abhängigkeitsmanagement) war der beliebteste Build System für Java-Projekte und alle von einem .__ benötigten externen JARs. Projekt (d. h. die Abhängigkeiten und Abhängigkeiten unseres Projekts) hatten manuell heruntergeladen und in einem Build-Skript angegeben werden.

Auf der anderen Seite ist mockito-core.jar nur Mockito-Klassen (auch mit Umgepacktes ASM und CGLIB). Bei Verwendung mit Maven oder Gradle erforderlich Abhängigkeiten (Hamcrest und Objenesis) werden von diesen Tools verwaltet (wird automatisch heruntergeladen und auf einen Testklassenpfad gesetzt). Es erlaubt zu gebrauchte Versionen überschreiben (zum Beispiel, wenn unsere Projekte niemals, aber abwärtskompatible Version verwenden), aber was wichtiger ist, diese Abhängigkeiten werden nicht in mockito-all.jar versteckt, was .__ erlaubt. Mögliche Versionsinkompatibilität mit Abhängigkeitsanalyse erkannt Werkzeuge. Dies ist eine viel bessere Lösung, wenn das verwaltete Werkzeug der Abhängigkeit .__ ist. in einem Projekt verwendet.

0
Pavel

Das hat bei mir funktioniert. Sie müssen nichts ausschließen. Ich habe gerade mockito-core statt mockito-all verwendet

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

In meinem Fall musste ich ein älteres hamcrest vom junit-vintage ausschließen:

<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é

Ich weiß, dass dies nicht die beste Antwort ist, aber wenn Sie den Klassenpfad nicht zum Laufen bringen können, ist dies eine Plan-B-Lösung.

In meinem Testklassenpfad habe ich die folgende Schnittstelle mit einer Standardimplementierung für die Methode "compareMismatch" hinzugefügt.

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

Was für mich funktionierte, war, die hamcrest-Gruppe vom Junit-Test-Compile auszuschließen.

Hier ist der Code aus meinem build.gradle:

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

Wenn Sie IntelliJ ausführen, müssen Sie möglicherweise gradle cleanIdea idea clean build ausführen, um die Abhängigkeiten erneut zu erkennen. 

0
Jason D