Abrufen von "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" beim Ausführen eines Tests in IntelliJ 10.5

233

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 einwandfrei, wenn es über die Befehlszeile mit Ant ausgeführt wird. Wenn es jedoch von IntelliJ ausgeführt wird, 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)

Ich vermute, dass es das falsche hamcrest.MatcherAssert verwendet. Wie finde ich, welches hamcrest.MatcherAssert verwendet wird (dh welche JAR-Datei für hamcrest.MatcherAssert verwendet wird)? AFAICT, das einzige Hamcrest-Glas in meinem Klassenpfad ist 1.3.RC2.

Verwendet IntelliJ IDEA eine eigene Kopie von JUnit oder Hamcrest?

Wie gebe ich den von IntelliJ verwendeten Laufzeit-CLASSPATH aus?

Noel Yap
quelle

Antworten:

272

Stellen Sie sicher, dass das Hamcrest- Glas in der Importbestellung höher ist als Ihr JUnit- Glas.

JUnit wird mit einer eigenen org.hamcrest.MatcherKlasse geliefert , die wahrscheinlich stattdessen verwendet wird.

Sie können stattdessen auch die Datei junit-dep-4.10.jar herunterladen und verwenden, bei der es sich um JUnit ohne die Hamcrest-Klassen handelt.

mockito enthält auch die Hamcrest-Klassen, sodass Sie es möglicherweise auch verschieben / neu anordnen müssen

Garrett Hall
quelle
1
OP sagte, dass sie bereits das '-dep-' Glas benutzten. Aber Ihre Vermutung, dass die Matcher-Klasse aus dem JUnit-Glas verwendet wird, klingt richtig. Es ist also wahrscheinlich, dass die IDE eine eigene Kopie von JUnit verwendet.
MatrixFrog
2
Ich habe IntelliJs Kopie von junit.jar und junit-4.8.jar entfernt, junit-dep-4.10.jar in IntelliJs lib / -Verzeichnis installiert, und das Problem tritt immer noch auf.
Noel Yap
8
JUnit 4.11 ist kompatibel mit Hamcrest 1.3 und JUnit 4.10 ist kompatibel mit Hamcrest 1.1 search.maven.org/remotecontent?filepath=junit/junit-dep/4.10/…
Muthu
23
Stellen Sie sicher, dass Sie NICHT Mockito-All verwenden, sondern Mockito-Core mit Ausschluss von Hamcrest
Ulf Lindback
1
Es ist 19.33 Uhr im Büro und ich arbeite an einer wichtigen Funktion, die ich bereitstellen muss, bevor ich in den Urlaub gehe. Es ist Freitag, ich bin nächste Woche in diesem Urlaub !!!!!! Wie zum Teufel konnte ich diesen Fehler jetzt bekommen !!!
Adelin
170

Dieses Problem tritt auch auf, wenn Sie Mockito-All auf Ihrem Klassenpfad haben, der bereits veraltet ist.

Wenn möglich, einfach Mockito-Core einschließen .

Maven-Konfiguration 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>
Tom Parkinson
quelle
2
Ganz so wie die neuen Versionen von Mockito Hamcrest auch mit Powermock enthalten!
Tom Parkinson
3
Sollte das Mockito-Core statt Mockito-All sein?
user944849
3
Sie könnten nur den Kern einschließen, wenn Sie ihn nur im Tempo von allen benötigen, aber das oben Genannte sollte in allen Fällen funktionieren. Die Reihenfolge der Abhängigkeiten ist das wichtige Bit, das mvn 3 in der Reihenfolge seiner Priorität von oben beginnt.
Tom Parkinson
3
Sie sollten NICHT mockito-all einschließen, da dies hamcrest 1.1 enthält, sondern mockito-core einschließen und hancrest davon ausschließen (was Sie nicht von allen tun können)
Ulf Lindback
1
"Wenn möglich, schließen Sie einfach Mockito-Core ein." OK, warum verwendet diese Antwort dann immer noch Mockito-All?
Stealth Rabbi
60

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

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

mvn dependency:tree -Dscope=test
Noel Yap
quelle
5
Ich hatte das gleiche Problem. Ich habe JUnit-dep und Hamcrest-core verwendet, aber Powermock war früher im Pom aufgeführt, was dazu führte, dass JUnit vor JUnit-dep und Hamcrest aufgenommen wurde.
John B
9
Mockito-All beinhaltet auch einige Hamcrest-Klassen. Es ist besser, Mockito-Core zu verwenden und die Hamcrest-Abhängigkeit auszuschließen.
Brambo
3
Bin gerade auf genau das gleiche Problem gestoßen. Die Lösung bestand darin, die Junit-Version auf 4.11 zu erhöhen, die mit hamcrest 1.3
r3mbol
Für diejenigen , in denen alle die Vorschläge nicht so gut funktionieren (Dependency Ordnung, exlusions, Entfernen ersetzen -allmit -core, etc ...): Ich hatte wieder hamcrest zurück auf Version 1.1 und jetzt funktioniert alles zu ändern.
Felix Hagspiel
1
Für mich hat es funktioniert, als ich meinen Import import static org.mockito.Matchers.anyString;vonimport static org.mockito.ArgumentMatchers.anyString;
Shrikant Prabhu
28

Das Folgende sollte heute am zutreffendsten sein. Beachten Sie, dass Junit 4.11 vom Hamcrest-Core abhängt. Sie sollten also nicht angeben müssen, dass Mockito-All überhaupt nicht verwendet werden kann, da es Hamcrest 1.1 enthält (nicht davon abhängt)

<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>
Ulf Lindback
quelle
3
Beachten Sie, dass JUnit 4.12 jetzt von Hamcrest-Core 1.3 abhängt.
JeeBee
Ausschluss von mockito-allhat mir geholfen, nicht mockito-core. Auch Hamcrest vor Mockito in pom.xmlWerken zu erklären .
Kirill
13

Das hat bei mir funktioniert, nachdem ich ein bisschen gekämpft 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>
Raul
quelle
Auch für mich. Wenn Sie Abhängigkeiten in diese Reihenfolge bringen, kann maven transitive Abhängigkeiten korrekt auflösen. Das explizite Ausschließen von Hamcrest vom Mockito-Core oder Mockito-All könnte jedoch sicherer sein, falls jemand Deps in Ihrem Pom nachbestellt.
Mat
4

Versuchen

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

anstatt

expectMessage(message)

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

Qiang Li
quelle
4

Ich weiß, dass dies ein alter Thread ist, aber was das Problem für mich gelöst hat, war das Hinzufügen des Folgenden zu meinen build.gradle-Dateien. Wie bereits oben erwähnt, liegt ein Kompatibilitätsproblem mit vormockito-all

Möglicherweise nützlicher Beitrag :

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'
Kai
quelle
1

Trotz der Tatsache, dass dies eine sehr alte Frage ist und wahrscheinlich viele der oben genannten Ideen viele Probleme gelöst haben, möchte ich die Lösung dennoch mit der Community teilen, die mein Problem behoben hat.

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

Und das führte zu dem Problem.

Irgendwie haben die Matcher Probleme mit Werten vom Typ Long. (Ich benutze JUnit oder Rest-Assured nicht so sehr, so idk. Genau warum, aber ich denke, dass die zurückgegebenen JSON-Daten nur Ganzzahlen enthalten.)

Was ich also getan habe, um das Problem tatsächlich zu beheben, war das Folgende. Anstatt zu verwenden:

long ID = ...;

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

Sie müssen nur in Integer umwandeln. 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 aufgrund falscher / unbekannter Datentypen ausgelöst werden kann.

Siro
quelle
0

Was für mich funktioniert hat, war, die Hamcrest-Gruppe von der Junit-Test-Kompilierung auszuschließen.

Hier ist der Code aus meinem build.gradle:

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

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

Jason D.
quelle
0

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

Ich habe ein Gradle-Projekt und wenn mein Abschnitt build.gradle-Abhängigkeiten so aussieht:

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) zwei Abhängigkeiten: Hamcrest und Objenesis (lassen Sie neu verpacktes ASM und CGLIB für einen Moment weg). Der Grund war, alles, was benötigt wird, in einem JAR zu haben, um es einfach auf einen Klassenpfad zu stellen. Es kann seltsam aussehen, aber bitte denken Sie daran, dass die Mockito-Entwicklung in Zeiten begann, in denen reines Ant (ohne Abhängigkeitsmanagement) das beliebteste Build-System für Java-Projekte war und alle externen JARs, die für ein Projekt erforderlich sind (dh die Abhängigkeiten unseres Projekts und ihre Abhängigkeiten) manuell heruntergeladen und in einem Build-Skript angegeben werden.

Auf der anderen Seite ist mockito-core.jar nur eine Mockito-Klasse (auch mit neu verpacktem ASM und CGLIB). Bei Verwendung mit Maven oder Gradle werden die erforderlichen Abhängigkeiten (Hamcrest und Objenesis) von diesen Tools verwaltet (automatisch heruntergeladen und in einen Testklassenpfad gestellt). Es ermöglicht das Überschreiben verwendeter Versionen (z. B. wenn unsere Projekte nie, sondern abwärtskompatible Versionen verwenden), aber was noch wichtiger ist, diese Abhängigkeiten sind nicht in mockito-all.jar verborgen, wodurch mögliche Versionsinkompatibilitäten mit Tools zur Abhängigkeitsanalyse erkannt werden können. Dies ist eine viel bessere Lösung, wenn das abhängigkeitsverwaltete Tool in einem Projekt verwendet wird.

Pavel
quelle
0

In meinem Fall musste ich einen älteren 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>
André
quelle
0

Das hat bei mir funktioniert. Sie müssen nichts ausschließen. Ich habe nur mockito-corestattdessen verwendetmockito-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'
Joni Lappalainen
quelle