NoSuchMethodError: org.hamcrest. matcher . descripbemismatch "在IntelliJ 10.5中运行测试时

我使用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(即它正在使用哪个jar文件hamcrest.MatcherAssert)?AFAICT,我的类路径中唯一的hamcrest jars是1.3.RC2。

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

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

122357 次浏览

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

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

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

Mockito也有hamcrest类,所以你可能需要移动\重新排序

问题是使用了错误的hamcrest.Matcher类,而不是hamcrest.MatcherAssert类。它是从junit-4.8依赖项中拉进来的,我的一个依赖项正在指定。

要在测试时查看来自哪个源的依赖项(和版本),请运行:

mvn dependency:tree -Dscope=test

当你的类路径上有mockito-all时,这个问题也会出现,这已经被弃用了。

如果可能的话,只包含mockito-core

Maven配置混合junit, mockito和hamcrest:

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

在经历了一些挣扎后,这对我来说很有效

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

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

试一试

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

而不是

expectMessage(message)

你可以编写一个自定义的ExpectedException或实用程序方法来封装代码。

对我来说,有效的方法是从junit测试编译中排除hamcrest组。

下面是build.gradle的代码:

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

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

我知道这不是最好的答案,但是如果您不能让类路径工作,这是一个B计划解决方案。

在我的测试类路径中,我为descripbemismatch方法添加了一个默认实现的接口。

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_();
}

我知道这是一个旧线程,但为我解决的问题是添加以下内容到我的构建。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'
尽管这是一个非常古老的问题 也许前面提到的许多想法解决了许多问题, 我仍然想与解决我的问题的社区分享解决方案。

我发现问题是一个名为“hasItem”的函数 我用它来检查json数组是否包含特定的项。 在我的例子中,我检查了类型为Long.

的值

这就产生了问题。

不知道为什么,matcher对Long类型的值有问题。 (我不太使用JUnit或Rest-Assured,所以idk。为什么, 但是我猜返回的JSON-data只包含整数。)

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

long ID = ...;


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

你只需要转换为Integer。 工作代码是这样的:

long ID = ...;


...
.then().assertThat()
.body("myArray", hasItem((int) ID));
这可能不是最好的解决方案, 但我只是想提一下,也可以因为错误/未知的数据类型而抛出异常

我有一个gradle项目,当我建立。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/ < / p >

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)由这些工具管理 (自动下载并放在测试类路径上)。它允许 重写已使用的版本(例如,如果我们的项目使用never, but 向后兼容版本),但更重要的是那些 依赖关系没有隐藏在mockito-all.jar中 通过依赖分析检测到可能的版本不兼容 工具。这是一个更好的解决方案时,依赖管理工具

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

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

截至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 在这里输入图像描述 < / p >

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