IntelliJ 10.5でテストを実行すると、「NoSuchMethodError:org.hamcrest.Matcher.describeMismatch」が発生する


233

JUnit-dep 4.10とHamcrest 1.3.RC2を使用しています。

次のようなカスタムマッチャーを作成しました。

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

Antを使用してコマンドラインから実行すると、完全に正常に動作します。しかし、IntelliJから実行すると、次のエラーで失敗します。

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)

私の推測では、間違ったhamcrest.MatcherAssertを使用しています。使用しているhamcrest.MatcherAssert(つまり、hamcrest.MatcherAssertに使用しているjarファイル)を見つけるにはどうすればよいですか?AFAICT、私のクラスパスの唯一のハムクレストjarは1.3.RC2です。

IntelliJ IDEAはJUnitまたはHamcrestの独自のコピーを使用していますか?

IntelliJが使用しているランタイムCLASSPATHを出力するにはどうすればよいですか?

回答:


272

hamcrest jarがJUnit jar よりもインポート順で高いことを確認してください。

JUnitには、org.hamcrest.Matcherおそらく代わりに使用されている独自のクラスが付属しています。

hamcrestクラスのないJUnitであるjunit-dep-4.10.jarをダウンロードして使用することもできます。

mockitoにはhamcrestクラスも含まれているため、移動/並べ替えも必要になる場合があります


1
OPは、すでに「-dep-」jarを使用していると述べました。しかし、JUnit jarのMatcherクラスを使用していることは間違いないでしょう。つまり、IDEが独自のJUnitのコピーを使用している可能性があります。
MatrixFrog 2011年

2
IntelliJのjunit.jarおよびjunit-4.8.jarのコピーを削除し、junit-dep-4.10.jarをIntelliJのlib /ディレクトリにインストールしましたが、それでも問題は発生します。
Noel Yap、

8
JUnitの4.11 Hamcrest 1.3と互換性があり、JUnitの4.10はHamcrest 1.1と互換性があり search.maven.org/remotecontent?filepath=junit/junit-dep/4.10/...
ムトゥ

23
必ずmockito-すべてを使用していないが、代わりにhamcrestを排除しmockitoコア作る
ウルフLindback

1
それは私が休暇に出かける前に私が提供しなければならない重要な機能に取り組んでいるオフィスで午後7時33分であり、金曜日です、私は来週その休暇にいます!!!!!! どうして私は今このエラーを得ることができるのか!
アデリン

170

この問題は、クラスパスにmockito-allがある場合にも発生しますが、すでに廃止されています。

可能であれば、mockito-coreを含めてください

junit、mockito、hamcrestを混合するためのMaven設定:

<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
mockitoの新しいバージョンには、powermockと同じhamcrestが含まれています。
トムパーキンソン

3
それはmockito-allではなくmockito-coreである必要がありますか?
user944849 14年

3
すべてのペースで必要な場合はコアのみを含めることができますが、上記はすべてのケースで機能します。依存関係の順序は、mvn 3が優先順位の高い順に上から始まる重要なビットです。
トムパーキンソン

3
hamcrest 1.1が含まれているため、mockito-allを含めないでください。代わりに、mockito-coreを含め、そこからhancrestを除外します(すべてから行うことはできません)
Ulf Lindback 14年

1
「可能であれば、mockito-coreを含めてください。」OK、それではなぜこの答えはまだmockito-allを使用するのですか?
ステルスラビ

60

問題はhamcrest.Matcher、ではなくhamcrest.MatcherAssert、間違ったクラスが使用されていたことでした。それは、私の依存関係の1つが指定していたjunit-4.8依存関係から引き出されていました。

テスト中にどのソースからどの依存関係(およびバージョン)が含まれているかを確認するには、次のコマンドを実行します。

mvn dependency:tree -Dscope=test

5
同じ問題がありました。私はJUnit-depとHamcrest-coreを使用していましたが、PowerMockを以前のpomにリストしていたため、JUnitがJUnit-depとHamcrestの前に含まれていました。
John B

9
また、mockito-allにはいくつかのHamcrestクラスが含まれています。mockito-coreを使用し、hamcrest依存関係を除外することをお勧めします。
Brambo 2012

3
まったく同じ問題に遭遇しました。ソリューションは、junitバージョンをhamcrest 1.3と互換性がある(つまり、「からのクラスを含む」)4.11にアップグレードしていました
r3mbol

すべての提案がうまく機能しなかった場合(依存関係の順序、除外、replace -allwithの削除-coreなど):hamcrestをバージョン1.1に戻す必要がありましたが、すべてが再び機能するようになりました。
Felix Hagspiel

1
私は私のインポートを変更したときに私のためにそれが働いたimport static org.mockito.Matchers.anyString;からimport static org.mockito.ArgumentMatchers.anyString;
Shrikantプラブー

28

以下は今日最も正しいはずです。junit 4.11はhamcrest-coreに依存しているため、hamcrest 1.1が含まれている(依存していない)ため、mockito-allは使用できないことを指定する必要はありません。

<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
JUnit 4.12がhamcrest-core 1.3に依存するようになりました。
JeeBee 2015年

mockito-allではなく、私を助けてからの除外mockito-corepom.xml作品ではモッキートの前にハムクレストを宣言しています。
キリル

13

これは少し苦労した後私のために働きました

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

わたしも。依存関係をこの順序で配置すると、Mavenが推移的な依存関係を正しく解決するのに役立ちます。ただし、mockito-coreまたはmockito-allからhamcrestを明示的に除外すると、誰かがpomでdepsを再注文した場合に、より安全になる場合があります。
マット

4

試す

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

の代わりに

expectMessage(message)

ExpectedExceptionコードをラップするカスタムまたはユーティリティメソッドを記述できます。


4

私はこれが古いスレッドであることを知っていますが、問題を解決したのは、build.gradleファイルに以下を追加することでした。すでに述べたように、との互換性の問題がありますmockito-all

おそらく役立つ投稿

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

これは非常に古い質問であり、おそらく前述のアイデアの多くが多くの問題を解決したという事実にもかかわらず、私の問題を解決したコミュニティと解決策を共有したいと思います。

問題は、JSON-Arrayに特定のアイテムが含まれているかどうかを確認するために使用していた「hasItem」という関数であることがわかりました。私の場合、Long型の値をチェックしました。

そして、これが問題につながりました。

どういうわけか、MatchersはLong型の値に問題があります。(私はJUnitやRest-Assuredをあまり使用していないので、まさにその理由ですが、返されたJSONデータには整数のみが含まれていると思います。)

だから私が実際に問題を修正するためにしたことは次のことでした。代わりに:

long ID = ...;

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

あなたはただ整数にキャストする必要があります。したがって、作業コードは次のようになります。

long ID = ...;

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

それはおそらく最善の解決策ではありませんが、間違った/不明なデータ型が原因で例外がスローされる可能性があることも述べておきたいと思います。


0

私にとってうまくいったのは、junitテストのコンパイルからhamcrestグループを除外することでした。

これが私のbuild.gradleのコードです。

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

IntelliJを実行gradle cleanIdea idea clean buildしている場合は、実行して依存関係を再度検出する必要がある場合があります。


0

それが最善の答えではないことは知っていますが、クラスパスを機能させることができない場合、これはプランBのソリューションです。

テストクラスパスに、describeMismatchメソッドのデフォルト実装を含む次のインターフェースを追加しました。

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

私はgradleプロジェクトを持っており、私のbuild.gradleの依存関係セクションは次のようになります:

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

それはこの例外につながります:

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)

この問題を修正するために、「mockito-all」を「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'
}

mockito-allmockito-coreの間の説明は、https//solidsoft.wordpress.com/2012/09/11/beyond-the-mockito-refcard-part-3-mockito-core-vs-mockitoにあります。 -all-in-mavengradle-based-projects /

mockito-all.jarの他に、Mockito自体(1.9.5以降)には、HamcrestとObjenesisの2つの依存関係も含まれています(しばらくの間、再パッケージ化されたASMとCGLIBは省略しましょう)。その理由は、クラスパスに置くために1つのJAR内に必要なものをすべて持つためでした。奇妙に見えるかもしれませんが、純粋なAnt(依存関係管理なし)がJavaプロジェクトの最も一般的なビルドシステムであり、プロジェクトに必要なすべての外部JAR(つまり、プロジェクトの依存関係とその依存関係)があったときにMockito開発が始まったことを思い出してください手動でダウンロードし、ビルドスクリプトで指定します。

一方、mockito-core.jarはMockitoクラスです(ASMとCGLIBも再パッケージ化されています)。MavenまたはGradleで使用する場合、必要な依存関係(HamcrestおよびObjenesis)はこれらのツールによって管理されます(自動的にダウンロードされ、テストクラスパスに置かれます)。使用されているバージョンを上書きすることができます(たとえば、プロジェクトで決して使用しないが、下位互換性のあるバージョンを使用する場合)。ただし、依存関係分析ツールとのバージョンの非互換性の可能性を検出できるようにするために、これらの依存関係がmockito-all.jar内に隠されていないことがより重要です。これは、依存関係管理ツールがプロジェクトで使用される場合のはるかに優れたソリューションです。


0

私の場合、古いユニットを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

これでうまくいきました。何も除外する必要はありません。mockito-core代わりに使用しました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'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.