ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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


j
javamonkey79

确保导入订单上的 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
“更高的进口”是什么意思?
m
marcin

当你的类路径上有 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 ?
A
Alex

问题是使用了错误的 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; 时它起作用了
U
Ulf Lindback

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

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

<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.xml 中重新排序 deps。
K
Kai

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

m
mlegge

尝试

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

代替

expectMessage(message)

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


z
zeinkap

截至 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


S
Siro

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

我发现问题出在一个名为“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));

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


P
Pasha

我有一个 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 中,这允许检测到与依赖项分析工具可能存在的版本不兼容。当在项目中使用依赖管理工具时,这是更好的解决方案。


A
André

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

J
Joni Lappalainen

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

J
Jason D

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

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

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

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


F
Francis

我知道这不是最好的答案,但如果你不能让类路径工作,这是一个 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_();
}

U
Udara Seneviratne

对于 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>

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅