242

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

4

15 回答 15

278

确保导入订单上的hamcrest jar 高于JUnit jar。

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

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

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

于 2011-10-24T15:47:33.550 回答
177

当你的类路径上有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>
于 2013-05-24T12:49:38.663 回答
62

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

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

mvn dependency:tree -Dscope=test
于 2011-10-24T21:48:53.097 回答
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>
于 2014-11-21T10:17:29.740 回答
15

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

<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>
于 2014-04-12T20:13:06.110 回答
5

我知道这是一个旧线程,但为我解决的问题是将以下内容添加到我的 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'
于 2017-05-22T06:11:17.630 回答
4

尝试

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

代替

expectMessage(message)

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

于 2015-02-05T23:14:53.250 回答
2

截至 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 并抛出异常 - 在此处输入图像描述

于 2020-07-06T17:34:51.170 回答
1

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

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

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

于 2017-11-27T23:00:12.063 回答
1

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

于 2019-01-06T20:09:56.787 回答
1

就我而言,我不得不从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>
于 2019-02-09T12:38:46.063 回答
1

这对我有用。不需要排除任何东西。我只是mockito-coremockito-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'
于 2019-08-14T10:57:05.197 回答
0

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

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

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

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

于 2016-05-10T17:48:06.283 回答
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_();
}
于 2016-05-30T13:20:27.480 回答
0

对于 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>
于 2021-03-30T13:19:13.873 回答