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を出力するにはどうすればよいですか?
問題は、hamcrest.Matcher
ではなく、間違ったhamcrest.MatcherAssert
クラスが使用されていたことです。それはjunit-4.8依存関係から引き寄せられていたもので、私の依存関係の1つが指定していました。
テスト中にどのソースからどの依存関係(およびバージョン)が含まれているかを確認するには、次を実行します。
mvn dependency:tree -Dscope=test
hamcrest jarがインポート順序でJUnit jarよりも高いことを確認してください。
JUnitには、おそらく代わりに使用されている独自のorg.hamcrest.Matcher
クラスが付属しています。
HamcrestクラスのないJUnitである代わりにjunit-dep-4.10.jarをダウンロードして使用することもできます。
mockitoにはハムクレストクラスも含まれているので、移動/並べ替えが必要になる場合があります
この問題は、クラスパスに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>
今日、以下が最も正しいはずです。 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>
これは少し苦労した後私のために働いた
<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>
試して
expect(new ThrowableMessageMatcher(new StringContains(message)))
の代わりに
expectMessage(message)
カスタムExpectedException
またはユーティリティメソッドを記述して、コードをラップすることができます。
私はこれが古いスレッドであることを知っていますが、問題を解決したのは、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'
これは非常に古い質問であり、おそらく前述のアイデアの多くは多くの問題を解決したという事実にもかかわらず、私の問題を解決したコミュニティと解決策を共有したいと思っています。
問題は、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));
これはおそらく最善の解決策ではありませんが、間違った/不明なデータ型が原因で例外がスローされる可能性があることに言及したかっただけです。
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-allとmockito-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内に隠されていないためです。これは、プロジェクトで依存関係管理ツールを使用する場合のはるかに優れたソリューションです。
これは私のために働いた。何も除外する必要はありません。 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'
私の場合、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>
それが最善の答えではないことは知っていますが、クラスパスを機能させることができない場合、これはプラン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_();
}
私のために働いたのは、junitテストコンパイルからhamcrestグループを除外することでした。
Build.gradleのコードは次のとおりです。
testCompile ('junit:junit:4.11') {
exclude group: 'org.hamcrest'
}
IntelliJを実行している場合は、gradle cleanIdea idea clean build
を実行して依存関係を再度検出する必要があります。