43

JUnit & Hamcrest 组合的另一个实例NoSuchMethodError。违规代码:

assertThat(dirReader.document(0).getFields(), hasItem(
    new FeatureMatcher<IndexableField, String>(equalTo("Patisnummer"), "Field key", "Field key") {
        @Override
        protected String featureValueOf(IndexableField actual) {
            return actual.name();
        } } ));

注释IndexerTest.java中的第 152–157行(提交ac72ce

导致 NoSuchMethodError(有关完整输出,请参见http://db.tt/qkkkTE78 ):

java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V
at org.hamcrest.FeatureMatcher.matchesSafely(FeatureMatcher.java:43)
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:55)
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:25)
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:14)
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:55)
at org.junit.Assert.assertThat(Assert.java:770)
at org.junit.Assert.assertThat(Assert.java:736)
at indexer.IndexerTest.testIndexContainsField(IndexerTest.java:152)

设置:

  • JUnit 4.11
  • 汉克雷斯特 1.3
  • 使用 Maven 的 surefire 插件(2.14 版),该插件使用其 JUnitCoreProvider
  • Java 7 (OpenJDK)
  • 参见pom(提交ac72ce

背景:

ANoSuchMethodError是由调用不存在的方法的(编译的)类引起的。JUnit + Hamcrest 组合的具体情况describeMismatch通常是由 JUnit 中包含的 Hamcrest 类与 Hamcrest 库中这些类的版本之间的不兼容引起的。

解决 NoSuchMethodError 的尝试:

  • pom 包含对 Hamcrest-library 1.3、Hamcrest-core 1.3 和 JUnit 4.11 的显式依赖(按此顺序),正如Garrett Hall在运行测试时在回答Getting "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" 时所建议的那样智能 10.5

  • 根据 JUnit 文档,JUnit 4.11 Maven 依赖不再包括已编译的 Hamcrest 类,而是依赖于 Hamcrest-core 1.3;所以不NoSuchMethodError应该发生。

  • 按照Dan回答junit 和 hamcrest 声明时的mvn dependency:tree建议检查依赖关系树,显示对 Hamcrest 1.3 和 JUnit 4.11 的显式依赖关系,并且对这些文件没有其他依赖关系(有关完整输出,请参见http://db.tt/C2OfTDJB)。

  • 在另一项测试中NoSuchMethodError,通过使用以下方法避免了这种情况:

    assertThat(
        "Zylab detector not available",
        d.getDetectors(),
        hasItem(Matchers.<Detector>instanceOf(ZylabMetadataXmlDetector.class)));
    

    IndexerTest.java (commit ac72ce ) 的第 120–123 行,而不是更明显的:

    assertThat(
        "Zylab detector not available",
        d.getDetectors(),
        hasItem(isA(ZylabMetadataDetector.class));
    

    我不确定显式类型参数<Detector>,使用instanceOf而不是isA,对 Hamcrest 的显式引用Matchers,或者这些的组合避免了NoSuchMethodException; 在摆弄并尝试不同的事情之后,它起作用了。

  • 使用显式类型参数并不能解决/避免错误。

  • 使用派生自的类BaseMatcher而不是FeatureMatcher没有解决/避免错误。

想法如何解决NoSuchMethodError

4

8 回答 8

27

这个博客帮助我解决了同样的问题:

https://tedvinke.wordpress.com/2013/12/17/mixing-junit-hamcrest-and-mockito-explaining-nosuchmethoderror/

在 Mockito 和 Junit 的依赖项中,作者添加了排除:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <exclusions>
        <exclusion>
            <artifactId>hamcrest-core</artifactId>
            <groupId>org.hamcrest</groupId>
        </exclusion>
    </exclusions>
</dependency>
于 2014-03-04T12:24:50.237 回答
2

也许其他 JAR 之一具有较旧版本的 HamcrestMatcherBaseMatcher. 这是包含后者的 JAR 列表,尽管我不知道该站点有多全面。是否有一个 Maven 插件可以向您显示包含类似于依赖树的类的所有依赖项?

于 2013-04-07T00:04:13.933 回答
2

使用David 的提示以及如何在 Bash 的分隔符上拆分字符串?导致以下 bash 脚本:

( IFS=":"; for i in `mvn dependency:build-classpath | grep -v '\[INFO\]'`; do jar tf $i | awk "{print \"$i\\t\" \$1}"; done | grep Matcher )

(在线http://www.kaspervandenberg.net/2013/scripts/findDependencyClass.sh

它发现依赖项JGlobus-Core-2.0.4有自己的org.hamcrest.BaseMatcher,org.hamcrest.CoreMatchersorg.hamcrest.Matcher.

于 2013-04-09T16:59:01.253 回答
2

如果您使用的是 Eclipse,“打开类型”工具 (CTRL+SHIFT+T) 可以帮助您找到有问题的包。只需搜索类名(例如,Description),来自不同 JAR 的同一类的多次出现是危险信号。

于 2013-09-25T00:12:52.737 回答
2

对我有用的是重新排序依赖项。我不得不使用 junit, mockito 而不是 mockito, junit。

Mockito 1.9.5 使用 hamcrest 1.1,它不兼容并会导致问题。

于 2014-10-22T23:38:22.390 回答
1

对于Gradle作为构建工具的项目:

testCompile("junit:junit:4.11") {
     exclude group: 'org.hamcrest', module: 'hamcrest-core'
     exclude group: 'org.hamcrest', module: 'hamcrest-library' 
}
testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3'
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
于 2017-03-18T14:55:09.810 回答
0

如果您使用的是 Eclipse:对我来说,在 eclipse-> 项目属性->Java 构建路径中将 mockito-all-1.9.5.jar 移动到“订单和导出”列表的底部就可以了。就在上面我有 junit-4.11.jar 和上面那个 hamcrest-core-1.3.jar

于 2015-07-14T08:50:13.943 回答
0

我用下面的代码jar hell在我的项目中解决了这个问题:Gradle

    testCompile (group: 'junit', name: 'junit', version: '4+') {
        exclude group: 'org.hamcrest'
    }
    testCompile ('org.mockito:mockito-core:1+') {
        exclude group: 'org.hamcrest'
    }
    testCompile 'org.hamcrest:java-hamcrest:2.0.0.0'
于 2016-06-07T14:57:52.990 回答