Mendapatkan “NoSuchMethodError: org.hamcrest.Matcher.describeMismatch” saat menjalankan tes di IntelliJ 10.5

233

Saya menggunakan JUnit-dep 4.10 dan Hamcrest 1.3.RC2.

Saya telah membuat pencocokan khusus yang terlihat seperti berikut:

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

Ini berfungsi dengan baik ketika dijalankan dari baris perintah menggunakan Ant. Tetapi ketika dijalankan dari IntelliJ, gagal dengan:

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)

Dugaan saya adalah bahwa ia menggunakan hamcrest.MatcherAssert yang salah. Bagaimana cara menemukan mana yang menggunakan hamcrest.MatcherAssert (yaitu file jar mana yang digunakan untuk hamcrest.MatcherAssert)? AFAICT, satu-satunya guci hamcrest di classpath saya adalah 1.3.RC2.

Apakah IntelliJ IDEA menggunakan salinan JUnit atau Hamcrest sendiri?

Bagaimana saya menampilkan runtime CLASSPATH yang digunakan IntelliJ?

Noel Yap
sumber

Jawaban:

272

Pastikan toples hamcrest lebih tinggi pada pesanan impor daripada JUnit Anda toples .

JUnit datang dengan sendiriorg.hamcrest.Matcher yang mungkin digunakan sebagai gantinya.

Anda juga dapat mengunduh dan menggunakan junit-dep-4.10.jar sebagai ganti JUnit tanpa kelas hamcrest.

mockito juga memiliki kelas hamcrest di dalamnya, jadi Anda mungkin perlu memindahkan \ atur ulangnya juga

Garrett Hall
sumber
1
OP mengatakan mereka sudah menggunakan toples '-dep-'. Tapi tebakan Anda bahwa itu menggunakan kelas Matcher dari toples JUnit kedengarannya benar. Jadi, mungkin IDE menggunakan salinan JUnit sendiri.
MatrixFrog
2
Saya menghapus salinan junit.jar dan junit-4.8.jar IntelliJ, menginstal junit-dep-4.10.jar ke lib / direktori IntelliJ, dan masalahnya masih terjadi.
Noel Yap
8
JUnit 4.11 kompatibel dengan Hamcrest 1.3 dan JUnit 4.10 kompatibel dengan Hamcrest 1.1 search.maven.org/remotecontent?filepath=junit/junit-dep/4.10/…
Muthu
23
pastikan Anda TIDAK menggunakan mockito-all, tetapi mockito-core dengan pengecualian hamcrest
Ulf Lindback
1
Sekarang sudah jam 19.33 di kantor dan saya sedang mengerjakan fitur penting yang harus saya sampaikan sebelum pergi berlibur dan ini hari Jumat, saya akan berlibur lagi minggu depan !!!!!! Bagaimana saya bisa mendapatkan kesalahan ini sekarang !!!
Adelin
170

Masalah ini juga muncul ketika Anda memiliki mockito-semua di jalur kelas Anda, yang sudah usang.

Jika mungkin sertakan saja mockito-core .

Konfigurasi Maven untuk mencampur junit, mockito dan 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
sumber
2
Cukup seperti versi baru mockito termasuk hamcrest juga sama dengan powermock!
Tom Parkinson
3
Haruskah itu mockito-core bukan mockito-all?
user944849
3
Anda dapat memasukkan inti hanya jika Anda hanya membutuhkannya dalam kecepatan semua tetapi yang di atas harus bekerja dalam semua kasus. Urutan dependensi adalah bit penting mvn 3 dimulai dari atas dalam urutan prioritas.
Tom Parkinson
3
Anda TIDAK boleh memasukkan mockito-semua karena itu termasuk hamcrest 1.1, sebagai gantinya sertakan mockito-core dan mengecualikan hancrest darinya (yang tidak dapat Anda lakukan dari semuanya)
Ulf Lindback
1
"Jika mungkin, sertakan saja mockito-core." Oke, lalu mengapa jawaban ini masih menggunakan mockito-all?
Stealth Rabbi
60

Masalahnya adalah yang salah hamcrest.Matcher, bukanhamcrest.MatcherAssert , sedang digunakan. Itu ditarik dari dependensi Junit-4.8 yang ditentukan salah satu dependensi saya.

Untuk melihat dependensi apa (dan versi) yang disertakan dari sumber apa saat pengujian, jalankan:

mvn dependency:tree -Dscope=test
Noel Yap
sumber
5
Saya memiliki masalah yang sama. Saya menggunakan JUnit-dep dan Hamcrest-core tetapi saya memiliki Powermock yang terdaftar sebelumnya di pom yang mengakibatkan JUnit dimasukkan sebelum JUnit-dep dan Hamcrest.
John B
9
Juga mockito-semua termasuk beberapa kelas Hamcrest. Lebih baik menggunakan mockito-core dan mengecualikan ketergantungan hamcrest.
Brambo
3
Baru saja menemukan masalah yang sama persis. Solution menaikkan versi junit ke 4.11 yang kompatibel (yaitu "berisi kelas dari") dengan hamcrest 1.3
r3mbol
Bagi mereka yang semua sarannya tidak berfungsi dengan baik (urutan Ketergantungan, pengecualian, hapus ganti -alldengan -core, dll ...): Saya harus mengubah hamcrest kembali ke versi 1.1 dan sekarang semuanya berfungsi lagi.
Felix Hagspiel
1
bagi saya itu berhasil ketika saya mengubah impor saya import static org.mockito.Matchers.anyString;dariimport static org.mockito.ArgumentMatchers.anyString;
Shrikant Prabhu
28

Berikut ini adalah yang paling benar hari ini. Catatan, junit 4.11 tergantung pada hamcrest-core, jadi Anda tidak perlu menentukan bahwa sama sekali, mockito-semua tidak dapat digunakan karena itu termasuk (tidak tergantung pada) 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>
Ulf Lindback
sumber
3
Perhatikan bahwa JUnit 4.12 sekarang tergantung pada hamcrest-core 1.3.
JeeBee
Pengucilan dari mockito-allmembantu saya, bukan mockito-core. Juga mendeklarasikan Hamcrest sebelum Mockito dalam pom.xmlkarya.
Kirill
13

Ini bekerja untuk saya setelah berjuang sedikit

<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
sumber
Sama untuk ku. Menempatkan dependensi dalam urutan ini membantu maven untuk menyelesaikan deps transitif dengan benar. Secara eksplisit mengecualikan hamcrest dari mockito-core atau mockito-semua mungkin lebih aman, jika seseorang menata ulang deps di pom Anda.
Mat
4

Mencoba

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

dari pada

expectMessage(message)

Anda dapat menulis metode kustom ExpectedExceptionatau utilitas untuk membungkus kode.

Qiang Li
sumber
4

Saya tahu ini adalah utas lama tetapi yang memecahkan masalah bagi saya adalah menambahkan yang berikut ini ke file build.gradle saya. Seperti yang sudah dinyatakan di atas ada masalah kompatibilitas denganmockito-all

Pos yang mungkin bermanfaat :

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
sumber
1

Terlepas dari kenyataan bahwa ini adalah pertanyaan yang sangat lama dan mungkin banyak dari ide-ide tersebut menyelesaikan banyak masalah, saya masih ingin berbagi solusi dengan komunitas yang memperbaiki masalah saya.

Saya menemukan bahwa masalahnya adalah fungsi yang disebut "hasItem" yang saya gunakan untuk memeriksa apakah JSON-Array berisi item tertentu. Dalam kasus saya, saya memeriksa nilai tipe Long.

Dan ini menyebabkan masalah.

Entah bagaimana, Pencocokan memiliki masalah dengan nilai tipe Long. (Saya tidak menggunakan JUnit atau Rest-Assured begitu banyak idk. Persis mengapa, tapi saya rasa JSON-data yang dikembalikan hanya berisi Integer.)

Jadi yang saya lakukan untuk memperbaiki masalah adalah sebagai berikut. Alih-alih menggunakan:

long ID = ...;

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

Anda hanya perlu melakukan cast ke Integer. Jadi kode kerjanya terlihat seperti ini:

long ID = ...;

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

Itu mungkin bukan solusi terbaik, tapi saya hanya ingin menyebutkan bahwa pengecualian juga dapat dilempar karena tipe data yang salah / tidak dikenal.

Siro
sumber
0

Apa yang berhasil bagi saya adalah mengecualikan kelompok hamcrest dari kompilasi tes junit.

Berikut adalah kode dari build.gradle saya:

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

Jika Anda menjalankan IntelliJ, Anda mungkin perlu menjalankan gradle cleanIdea idea clean builduntuk mendeteksi dependensi lagi.

Jason D
sumber
0

Saya tahu itu bukan jawaban terbaik, tetapi jika Anda tidak dapat membuat classpath bekerja, ini adalah solusi rencana B.

Dalam classpath pengujian saya, saya menambahkan antarmuka berikut dengan implementasi default untuk metode descriptionMismatch.

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
sumber
0

Saya memiliki proyek gradle dan ketika bagian dependensi build.gradle saya terlihat seperti ini:

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

itu mengarah ke pengecualian ini:

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)

untuk memperbaiki masalah ini, saya telah mengganti "mockito-all" dengan "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'
}

Penjelasan antara mockito-all dan mockito-core dapat ditemukan di sini: https://solidsoft.wordpress.com/2012/09/11/beyond-the-mockito-refcard-part-3-mockito-core-vs-mockito -semua-dalam-proyek berbasis-mavengradle /

mockito-all.jar selain Mockito sendiri mengandung juga (pada 1.9.5) dua dependensi: Hamcrest dan Objenesis (mari kita hilangkan ASM dan CGLIB yang dikemas ulang sejenak). Alasannya adalah untuk memiliki segala yang dibutuhkan di dalam satu JAR untuk meletakkannya di classpath. Ini mungkin terlihat aneh, tetapi tolong ingat bahwa pengembangan Mockito dimulai pada saat ketika semut murni (tanpa manajemen ketergantungan) adalah sistem pembangunan yang paling populer untuk proyek-proyek Java dan semua JAR eksternal yang diperlukan oleh suatu proyek (yaitu ketergantungan proyek kami dan ketergantungannya) telah untuk diunduh secara manual dan ditentukan dalam skrip build.

Di sisi lain mockito-core.jar hanya kelas Mockito (juga dengan ASM dan CGLIB yang dikemas ulang). Ketika menggunakannya dengan Maven atau Gradle, dependensi yang diperlukan (Hamcrest dan Objenesis) dikelola oleh alat-alat tersebut (diunduh secara otomatis dan dimasukkan ke dalam jalur tes). Hal ini memungkinkan untuk menimpa versi yang digunakan (misalnya jika proyek kami tidak pernah menggunakan, tetapi versi yang kompatibel ke belakang), tetapi yang lebih penting ketergantungan itu tidak tersembunyi di dalam mockito-all.jar apa yang memungkinkan untuk mendeteksi kemungkinan ketidaksesuaian versi dengan alat analisis ketergantungan. Ini adalah solusi yang jauh lebih baik ketika alat yang dikelola ketergantungan digunakan dalam suatu proyek.

Pavel
sumber
0

Dalam kasus saya, saya harus mengecualikan hamcrest yang lebih tua dari 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>
André
sumber
0

Ini berhasil untuk saya. Tidak perlu mengecualikan apa pun. Saya hanya menggunakan mockito-coresajamockito-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
sumber