在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,在我的类路径中唯一的hamcrest jar是1.3.RC2。

IntelliJ IDEA是否使用它自己的JUnit或Hamcrest副本?

如何输出IntelliJ使用的运行时CLASSPATH?

Answers:


272

确保hamcrest jar在导入顺序上高于JUnit jar。

JUnit带有自己的org.hamcrest.Matcher类,该类可能正在被使用。

您也可以下载并使用junit-dep-4.10.jar而不是没有hamcrest类的JUnit。

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/…–
Muthu

23
确保您没有使用所有的模仿者,而是使用了不包含hamcrest的模仿者核心
Ulf Lindback 2014年

1
现在是办公室晚上7:33,我正在研究一项重要的功能,在休假之前我必须提供该功能,而现在是星期五,下周在休假中!真该死我现在要得到这个错误!
阿德林

170

当您已经在类路径上使用了mockito-all时,也会出现此问题。

如果可能的话,只需包括模仿主体

用于混合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
新版的模仿者包括hamcrest,也与powermock一样!
汤姆·帕金森

3
应该是mockito-core而不是mockito-all吗?
user944849 2014年

3
如果只需要核心,则可以只包含核心,但是以上内容在所有情况下都适用。依存关系的顺序是重要的位,mvn 3从优先级的顶部开始。
汤姆·帕金森

3
您不应该包括mockito-all,因为其中包括hamcrest 1.1,而应包括mockito-core并从其中排除hancrest(您不能
一概而论

1
“如果可能的话,只包括mockito-core。”。好的,那为什么这个答案仍然使用模仿所有人?
Stealth Rabbi

60

问题是使用了错误的类而hamcrest.Matcher不是hamcrest.MatcherAssert类。这是从junit-4.8依赖项中提取的,这是我的一个依赖项。

要查看在测试时从哪个来源包含了哪些依赖项(和版本),请运行:

mvn dependency:tree -Dscope=test

5
我遇到过同样的问题。我使用的是JUnit-dep和Hamcrest-core,但在pom中较早地列出了Powermock,这导致JUnit包含在JUnit-dep和Hamcrest之前。
约翰B

9
此外,mockito-all包括一些Hamcrest类。最好使用模仿内核并排除hamcrest依赖项。
布兰博2012年

3
只是偶然发现了完全相同的问题。解决方案是将junit版本升级到与hamcrest 1.3兼容(即“包含以下类”)的4.11
r3mbol 2013年

对于那些所有建议都无法正常工作的问题(依赖关系顺序,排除,删除替换-all-core等):我不得不将hamcrest改回1.1版,现在一切都可以正常工作了。
Felix Hagspiel '19

1
对我来说,当我将进口商品import static org.mockito.Matchers.anyString;import static org.mockito.ArgumentMatchers.anyString;
Shrikant Prabhu就

28

以下是当今最正确的方法。请注意,junit 4.11依赖于hamcrest-core,因此您完全不需要指定完全不能使用mockito-all,因为它包含(不依赖于)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
注意,JUnit 4.12现在依赖于hamcrest-core 1.3。
2015年

被排除mockito-all在外对我没有帮助mockito-core。同时在pom.xml作品中向Mockito宣告Hamcrest 。
基里尔'18

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正确解决传递性dep。但是,如果有人在您的pom中重新排列副驾驶,则将嘲笑明确地排除在模仿核心或模仿所有之外可能更安全。

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

尽管这是一个非常老的问题,并且可能有许多前面提到的想法解决了许多问题,但我仍然想与解决我的问题的社区分享解决方案。

我发现问题是一个名为“ hasItem”的函数,该函数用于检查JSON-Array是否包含特定项。就我而言,我检查了Long类型的值。

这导致了问题。

不知何故,匹配器在使用Long类型的值时遇到问题。(我为什么不使用JUnit或Rest-Assured这么多idk。这就是为什么,但是我想返回的JSON数据只包含Integer。)

因此,我实际解决此问题的方法如下。而不是使用:

long ID = ...;

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

您只需要转换为Integer。因此,工作代码如下所示:

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-core”代替了“ mockito-all”。

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

可以在此处找到嘲笑所有嘲笑核心之间的解释:https : //solidsoft.wordpress.com/2012/09/11/beyond-the-mockito-refcard-part-3-mockito-core-vs-mockito -基于Mavengradle的所有项目/

除了Mockito本身之外,mockito-all.jar还包含(从1.9.5版本开始)两个依赖项:Hamcrest和Objenesis(暂时省略重新打包的ASM和CGLIB)。原因是将所有JAR所需的一切都放在一个JAR路径中。它看起来可能很奇怪,但是请记住Mockito开发是在纯Ant(无依赖项管理)是Java项目最流行的构建系统以及项目所需的所有外部JAR(即,我们项目的依赖项及其依赖项)具有手动下载并在构建脚本中指定。

另一方面,mockito-core.jar只是Mockito类(也带有重新包装的ASM和CGLIB)。与Maven或Gradle结合使用时,所需的依赖项(Hamcrest和Objenesis)由这些工具管理(自动下载并放在测试类路径中)。它允许覆盖使用的版本(例如,如果我们的项目从不使用,而是向后兼容的版本),但更重要的是,这些依赖关系并未隐藏在嘲讽-all.jar中,这允许检测到与依赖关系分析工具可能存在的版本不兼容。在项目中使用依赖项管理工具时,这是更好的解决方案。


0

就我而言,我必须从junit-vintage中排除一个较旧的hamcrest:

<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'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.