web-dev-qa-db-ja.com

IntelliJ 10.5でテストを実行しているときに「NoSuchMethodError:org.hamcrest.Matcher.describeMismatch」を取得する

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を出力するにはどうすればよいですか?

214
Noel Yap

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

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

mvn dependency:tree -Dscope=test
58
Noel Yap

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

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

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

mockitoにはハムクレストクラスも含まれているので、移動/並べ替えが必要になる場合があります

260
Garrett Hall

この問題は、クラスパスに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>
158
Tom Parkinson

今日、以下が最も正しいはずです。 junit 4.11はhamcrest-coreに依存しているため、mockito-allはincludes(に依存しない)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

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

<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

試して

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

の代わりに

expectMessage(message)

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

4
Qiang Li

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

おそらく便利 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

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

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

そして、これが問題を引き起こしました。

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

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

long ID = ...;

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

整数にキャストするだけです。そのため、作業コードは次のようになりました。

long ID = ...;

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

これはおそらく最善の解決策ではありませんが、間違った/不明なデータ型が原因で例外がスローされる可能性があることに言及したかっただけです。

1
Siro

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以外のmockito-all.jarには、1.9.5の時点でHamcrestとObjenesisの2つの依存関係も含まれています(再パッケージ化されたASMとCGLIBをしばらく省略します)。その理由は、クラスパスに配置するために1つのJAR内に必要なものをすべて用意することでした。奇妙に見えるかもしれませんが、Mockito開発は純粋なAnt(依存関係管理なし)がJavaプロジェクトとプロジェクトに必要なすべての外部JAR(つまり、プロジェクトの依存関係とその依存関係)は手動でダウンロードし、ビルドスクリプトで指定する必要がありました。

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

0
Pavel

これは私のために働いた。何も除外する必要はありません。 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'
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
André

それが最善の答えではないことは知っていますが、クラスパスを機能させることができない場合、これはプラン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
Francis

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

Build.gradleのコードは次のとおりです。

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

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

0
Jason D