Bắt được NoSuchMethodError: org.hamcrest.Matcher.describeMismatch tựa khi chạy thử nghiệm trong IntelliJ 10.5


233

Tôi đang sử dụng JUnit-dep 4.10 và Hamcrest 1.3.RC2.

Tôi đã tạo một trình so khớp tùy chỉnh trông giống như sau:

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

Nó hoạt động hoàn toàn tốt khi chạy từ dòng lệnh bằng Ant. Nhưng khi chạy từ IntelliJ, nó thất bại với:

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)

Tôi đoán là nó đang sử dụng hamcrest sai.MatcherAssert. Làm cách nào để tìm hamcrest.MatcherAssert nào đang sử dụng (tức là tệp jar nào đang sử dụng cho hamcrest.MatcherAssert)? AFAICT, lọ hamcrest duy nhất trong đường dẫn lớp của tôi là 1.3.RC2.

IntelliJ IDEA có sử dụng bản sao của JUnit hoặc Hamcrest không?

Làm cách nào để tôi xuất CLASSPATH thời gian chạy mà IntelliJ đang sử dụng?

Câu trả lời:


272

Đảm bảo bình đựng hamcrest cao hơn trong đơn hàng nhập khẩu so với bình JUnit của bạn .

JUnit đi kèm với org.hamcrest.Matcherlớp riêng của nó có lẽ đang được sử dụng thay thế.

Bạn cũng có thể tải xuống và sử dụng Junit-dep-4.10.jar thay vào đó là JUnit mà không có các lớp hamcrest.

mockito cũng có các lớp hamcrest trong đó, vì vậy bạn có thể cần phải di chuyển \ sắp xếp lại nó


1
OP cho biết họ đã sử dụng bình '-dep-'. Nhưng bạn đoán rằng nó đang sử dụng lớp Matcher từ jar JUnit nghe có vẻ đúng. Vì vậy, có lẽ IDE đang sử dụng bản sao JUnit của riêng mình.
MatrixFrog

2
Tôi đã xóa bản sao Junit.jar và junit-4.8.jar của IntelliJ, đã cài đặt Junit-dep-4.10.jar vào thư mục lib / của IntelliJ và vấn đề vẫn xảy ra.
Noel Yap

8
JUnit 4.11 tương thích với Hamcrest 1.3 và JUnit 4.10 tương thích với Hamcrest 1.1 search.maven.org/remotecontent?filepath=junit/junit-dep/4.10/ /
Muthu

23
đảm bảo rằng bạn KHÔNG sử dụng mockito-all, mà thay vào đó là mockito-core với việc loại trừ hamcrest
Ulf Lindback

1
Đó là 7:33 PM trong văn phòng, tôi đang làm việc với một tính năng quan trọng mà tôi phải cung cấp trước khi ra ngoài trong một kỳ nghỉ và đó là thứ Sáu, tôi đang trong kỳ nghỉ đó vào tuần tới !!!!!! Làm thế nào da tôi có thể nhận được lỗi này bây giờ !!!
Adelin

170

Vấn đề này cũng phát sinh khi bạn có mockito-all trên đường dẫn lớp của bạn, thứ đã bị phản đối.

Nếu có thể chỉ bao gồm mockito-core .

Cấu hình Maven để trộn Junit, mockito và 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>

2
Khá giống như các phiên bản mới của mockito bao gồm hamcrest cũng giống với powermock!
Tom Parkinson

3
Đó có nên là mockito-core thay vì mockito-all?
dùng944849

3
Bạn có thể bao gồm chỉ cốt lõi nếu bạn chỉ cần nó theo tốc độ của tất cả tuy nhiên những điều trên sẽ hoạt động trong mọi trường hợp. Thứ tự của các phụ thuộc là bit quan trọng mvn 3 bắt đầu từ đầu theo thứ tự ưu tiên.
Tom Parkinson

3
Bạn KHÔNG nên bao gồm mockito-all vì bao gồm hamcrest 1.1, thay vào đó bao gồm mockito-core và loại trừ hancrest khỏi nó (điều mà bạn không thể làm từ tất cả)
Ulf Lindback

1
"Nếu có thể chỉ cần bao gồm mockito-core.". OK, vậy thì tại sao câu trả lời này vẫn sử dụng mockito-all?
Rabbi tàng hình

60

Vấn đề là lớp học sai hamcrest.Matcher, không hamcrest.MatcherAssertđược sử dụng. Điều đó đã được kéo vào từ một phụ thuộc Junit-4.8, một trong những phụ thuộc của tôi là chỉ định.

Để xem những phụ thuộc nào (và phiên bản) được bao gồm từ nguồn nào trong khi thử nghiệm, hãy chạy:

mvn dependency:tree -Dscope=test

5
Tôi gặp vấn đề tương tự. Tôi đã sử dụng JUnit-dep và Hamcrest-core nhưng tôi đã có Powermock được liệt kê trước đó trong pom, kết quả là JUnit được đưa vào trước JUnit-dep và Hamcrest.
John B

9
Ngoài ra mockito-tất cả bao gồm một số lớp Hamcrest. Tốt hơn là sử dụng lõi mockito và loại trừ sự phụ thuộc hamcrest.
Brambo

3
Chỉ vấp phải cùng một vấn đề. Giải pháp đã nâng phiên bản Junit lên 4.11 tương thích (nghĩa là "chứa các lớp từ") với hamcrest 1.3
r3mbol

Đối với những nơi mà tất cả những đề nghị đã không làm việc cũng như (theo thứ tự phụ thuộc, Loại trừ, loại bỏ thay thế -allbằng -core, vv ...): Tôi đã phải thay đổi lại hamcrest lên phiên bản 1.1 và bây giờ mọi thứ hoạt động trở lại.
Felix Hagspiel

1
đối với tôi nó hoạt động khi tôi thay đổi nhập khẩu import static org.mockito.Matchers.anyString;từimport static org.mockito.ArgumentMatchers.anyString;
Shrikant Mitchhu

28

Sau đây nên là chính xác nhất ngày hôm nay. Lưu ý, Junit 4.11 phụ thuộc vào lõi hamcrest, vì vậy bạn không cần phải xác định rằng tất cả, mockito-all không thể được sử dụng vì nó bao gồm (không phụ thuộc vào) 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>

3
Lưu ý rằng JUnit 4.12 hiện phụ thuộc vào lõi hamcrest 1.3.
JeeBee

Loại trừ mockito-allgiúp tôi, không mockito-core. Cũng tuyên bố Hamcrest trước Mockito trong pom.xmlcác tác phẩm.
Kirill

13

Điều này làm việc cho tôi sau khi đấu tranh một chút

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

Tương tự cho tôi. Đặt các phụ thuộc theo thứ tự này sẽ giúp maven giải quyết các phụ thuộc bắc cầu chính xác. Hoàn toàn loại trừ hamcrest khỏi mockito-core hoặc mockito - tất cả có thể an toàn hơn, trong trường hợp ai đó sắp xếp lại dep trong pom của bạn.
Mat

4

Thử

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

thay vì

expectMessage(message)

Bạn có thể viết một ExpectedExceptionphương thức tùy chỉnh hoặc tiện ích để bọc mã.


4

Tôi biết đây là một chủ đề cũ nhưng điều đã giải quyết vấn đề cho tôi là thêm phần sau vào tệp build.gradle của tôi. Như đã nêu ở trên, có một vấn đề tương thích vớimockito-all

Có thể bài viết hữu ích :

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'

1

Mặc dù thực tế đây là một câu hỏi rất cũ và có lẽ nhiều ý tưởng đã nói ở trên đã giải quyết được nhiều vấn đề, tôi vẫn muốn chia sẻ giải pháp với cộng đồng đã khắc phục vấn đề của tôi.

Tôi thấy rằng vấn đề là một hàm gọi là "hasItem" mà tôi đang sử dụng để kiểm tra xem JSON-Array có chứa một mục cụ thể hay không. Trong trường hợp của tôi, tôi đã kiểm tra giá trị của loại Long.

Và điều này dẫn đến vấn đề.

Bằng cách nào đó, các Matcher có vấn đề với các giá trị loại Long. (Tôi không sử dụng JUnit hoặc Rest-Assured rất nhiều vì vậy idk. Chính xác là tại sao, nhưng tôi đoán rằng dữ liệu JSON được trả về không chứa Số nguyên.)

Vì vậy, những gì tôi đã làm để thực sự khắc phục vấn đề là như sau. Thay vì sử dụng:

long ID = ...;

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

bạn chỉ cần chuyển sang Integer. Vì vậy, mã làm việc trông như thế này:

long ID = ...;

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

Đó có lẽ không phải là giải pháp tốt nhất, nhưng tôi chỉ muốn đề cập rằng ngoại lệ cũng có thể bị ném do các loại dữ liệu sai / không xác định.


0

Những gì làm việc cho tôi là loại trừ nhóm hamcrest khỏi biên dịch thử nghiệm Junit.

Đây là mã từ build.gradle của tôi:

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

Nếu bạn đang chạy IntelliJ, bạn có thể cần phải chạy gradle cleanIdea idea clean buildđể phát hiện lại các phụ thuộc.


0

Tôi biết đó không phải là câu trả lời hay nhất, nhưng nếu bạn không thể làm cho đường dẫn lớp hoạt động, thì đây là giải pháp kế hoạch B.

Trong classpath thử nghiệm của tôi, tôi đã thêm giao diện sau với cách triển khai mặc định cho phương thức 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_();
}

0

Tôi có một dự án lớp và khi phần phụ thuộc build.gradle của tôi trông như thế này:

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

nó dẫn đến ngoại lệ này:

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)

để khắc phục sự cố này, tôi đã thay thế "mockito-all" bằng "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'
}

Có thể tìm thấy lời giải thích giữa mockito-allmockito-core tại đây: https://solidsoft.wordpress.com/2012/09/11/beyond-the-mockito-refcard-part-3-mockito-core-vs-mockito -all-in-mavengradle-dựa-dự án /

mockito-all.jar ngoài Mockito cũng chứa (kể từ 1.9.5) hai phụ thuộc: Hamcrest và Objenesis (hãy bỏ qua ASM và CGLIB đóng gói lại trong giây lát). Lý do là để có mọi thứ cần thiết trong một JAR để đặt nó trên đường dẫn lớp. Nó có thể trông lạ, nhưng xin nhớ rằng sự phát triển của Mockito bắt đầu từ khi Ant thuần túy (không có quản lý phụ thuộc) là hệ thống xây dựng phổ biến nhất cho các dự án Java và tất cả các JAR bên ngoài được yêu cầu bởi một dự án (ví dụ như phụ thuộc dự án của chúng tôi) để được tải xuống bằng tay và được chỉ định trong tập lệnh xây dựng.

Mặt khác, mockito-core.jar chỉ là các lớp Mockito (cũng với ASM và CGLIB được đóng gói lại). Khi sử dụng nó với các phụ thuộc bắt buộc của Maven hoặc Gradle (Hamcrest và Objenesis) được quản lý bởi các công cụ đó (được tải xuống tự động và đưa vào đường dẫn thử nghiệm). Nó cho phép ghi đè các phiên bản đã sử dụng (ví dụ: nếu các dự án của chúng tôi sử dụng không bao giờ, nhưng phiên bản tương thích ngược), nhưng điều quan trọng hơn là những phụ thuộc đó không bị ẩn trong mockito-all.jar, điều này cho phép phát hiện sự không tương thích phiên bản có thể với các công cụ phân tích phụ thuộc. Đây là giải pháp tốt hơn nhiều khi công cụ quản lý phụ thuộc được sử dụng trong một dự án.


0

Trong trường hợp của tôi, tôi đã phải loại trừ một chiếc hamster cũ ra khỏi 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

Điều này làm việc cho tôi. Không cần loại trừ bất cứ điều gì. Tôi chỉ sử dụng mockito-corethay thế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'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.