【问题标题】:Getting "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" when running test in IntelliJ 10.5在 IntelliJ 10.5 中运行测试时出现“NoSuchMethodError:org.hamcrest.Matcher.describeMismatch”
【发布时间】:2011-12-13 18:12:14
【问题描述】:

我正在使用 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?

【问题讨论】:

    标签: java junit intellij-idea junit4 hamcrest


    【解决方案1】:

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

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

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

    mockito 也包含 hamcrest 类,因此您可能还需要移动\重新排序

    【讨论】:

    • OP 说他们已经在使用'-dep-' jar。但是您猜测它使用的是 JUnit jar 中的 Matcher 类听起来是对的。所以可能是 IDE 使用了自己的 JUnit 副本。
    • 我删除了IntelliJ的junit.jar和junit-4.8.jar的副本,将junit-dep-4.10.jar安装到IntelliJ的lib/目录下,问题依旧。
    • JUnit 4.11 与 Hamcrest 1.3 兼容,JUnit 4.10 与 Hamcrest 1.1 兼容 search.maven.org/remotecontent?filepath=junit/junit-dep/4.10/…
    • 确保你没有使用 mockito-all,而是使用 mockito-core 并排除 hamcrest
    • “导入更高”是什么意思?
    【解决方案2】:

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

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

    mvn dependency:tree -Dscope=test
    

    【讨论】:

    • 我遇到了同样的问题。我使用的是 JUnit-dep 和 Hamcrest-core,但我之前在 pom 中列出了 Powermock,这导致 JUnit 在 JUnit-dep 和 Hamcrest 之前被包含。
    • mockito-all 还包括一些 Hamcrest 类。最好使用 mockito-core 并排除 hamcrest 依赖。
    • 刚刚偶然发现了完全相同的问题。解决方案是将junit版本升级到与hamcrest 1.3兼容(即“包含来自”的类)的4.11
    • 对于那些所有建议都不起作用的人(依赖顺序、排除、删除用-core替换-all等...):我不得不将hamcrest改回1.1版现在一切都恢复正常了。
    • 对我来说,当我将导入从 import static org.mockito.ArgumentMatchers.anyString; 更改为 import static org.mockito.Matchers.anyString; 时它起作用了
    【解决方案3】:

    当您的类路径中有 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>
    

    【讨论】:

    • 新版本的 mockito 包括 hamcrest 也与 powermock 相同!
    • 应该是 mockito-core 而不是 mockito-all?
    • 如果您只需要核心,那么您可以只包含核心,但以上内容应该适用于所有情况。依赖的顺序是重要的位 mvn 3 从顶部开始按优先级排序。
    • 您不应该包含 mockito-all,因为它包含 hamcrest 1.1,而应包含 mockito-core 并从中排除 hancrest(您不能全部都这样做)
    • "如果可能的话,只包括 mockito-core。"。好的,那么为什么这个答案仍然使用 mockito-all ?
    【解决方案4】:

    经过一番挣扎后,这对我有用

    <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。
    【解决方案5】:

    以下应该是今天最正确的。请注意,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>
    

    【讨论】:

    • 请注意,JUnit 4.12 现在依赖于 hamcrest-core 1.3。
    • 排除 mockito-all 对我有帮助,而不是 mockito-core。还在 pom.xml 工作的 Mockito 之前声明 Hamcrest。
    【解决方案6】:

    试试

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

    而不是

    expectMessage(message)

    您可以编写自定义ExpectedException 或实用方法来包装代码。

    【讨论】:

      【解决方案7】:

      对我有用的是从 junit 测试编译中排除 hamcrest 组。

      这是我的 build.gradle 中的代码:

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

      如果您正在运行 IntelliJ,您可能需要运行 gradle cleanIdea idea clean build 以再次检测依赖项。

      【讨论】:

        【解决方案8】:

        我知道这不是最佳答案,但如果您无法让类路径正常工作,这是 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_();
        }
        

        【讨论】:

          【解决方案9】:

          我知道这是一个旧线程,但为我解决问题的方法是将以下内容添加到我的 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'
          

          【讨论】:

            【解决方案10】:

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

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

            这导致了问题。

            不知何故,Matchers 对 Long 类型的值有问题。 (我不使用 JUnit 或 Rest-Assured 这么多 idk。究竟为什么, 但我猜返回的 JSON 数据确实只包含整数。)

            所以我实际解决问题的方法如下。 而不是使用:

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

            您只需转换为整数。 所以工作代码看起来像这样:

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

            这可能不是最好的解决方案, 但我只想提一下,由于错误/未知的数据类型,也可能引发异常。

            【讨论】:

              【解决方案11】:

              我有一个 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(让我们省略重新打包的 ASM 和 CGLIB 片刻)。原因是拥有所需的一切 在一个 JAR 中将其放在类路径中。它可能看起来很奇怪, 但请记住,Mockito 的开发始于 纯 Ant(没有依赖管理)是最流行的构建 Java 项目的系统和所有外部 JAR 所需的 项目(即我们项目的依赖项及其依赖项)有 手动下载并在构建脚本中指定。

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

              【讨论】:

                【解决方案12】:

                就我而言,我不得不从 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>
                

                【讨论】:

                  【解决方案13】:

                  这对我有用。不需要排除任何东西。我只是用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'
                  

                  【讨论】:

                    【解决方案14】:

                    截至 2020 年 7 月,pom.xml 中的以下依赖项对我有用:

                    <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>4.13</version>
                    </dependency>
                    <dependency>
                        <groupId>org.hamcrest</groupId>
                        <artifactId>hamcrest</artifactId>
                        <version>2.1</version>
                    </dependency>
                    

                    有了这个 4.13 junit 库和 hamcrest,它在断言时使用 hamcrest.MatcherAssert 并抛出异常- enter image description here

                    【讨论】:

                      【解决方案15】:

                      对于 jUnit 4.12,以下依赖组合解决了我的问题。

                      <dependency>
                         <groupId>junit</groupId>
                         <artifactId>junit</artifactId>
                         <version>4.12</version>
                         <scope>test</scope>
                      </dependency>
                      <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>
                      

                      【讨论】:

                        猜你喜欢
                        • 2015-06-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-07-02
                        • 2018-12-01
                        • 2018-05-04
                        • 2014-08-31
                        相关资源
                        最近更新 更多