我正在使用 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?
确保导入订单上的 hamcrest jar 高于 JUnit jar。
JUnit 带有它自己的 org.hamcrest.Matcher
类,可能正在使用它。
您也可以下载并使用 junit-dep-4.10.jar,它是没有 hamcrest 类的 JUnit。
mockito 也有 hamcrest 类,因此您可能还需要移动\重新排序
当你的类路径上有 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>
问题是使用了错误的 hamcrest.Matcher
而不是 hamcrest.MatcherAssert
类。这是从我的依赖项之一指定的 junit-4.8 依赖项中提取的。
要查看测试时从哪个来源包含哪些依赖项(和版本),请运行:
mvn dependency:tree -Dscope=test
-core
替换 -all
等):我不得不将 hamcrest 改回 1.1 版,现在一切都恢复正常了。
import static org.mockito.ArgumentMatchers.anyString;
更改为 import static org.mockito.Matchers.anyString;
时它起作用了
以下应该是今天最正确的。请注意,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>
mockito-all
中排除对我有帮助,而不是 mockito-core
。在 pom.xml
中在 Mockito 之前声明 Hamcrest 也有效。
经过一番挣扎后,这对我有用
<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>
我知道这是一个旧线程,但为我解决的问题是将以下内容添加到我的 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'
尝试
expect(new ThrowableMessageMatcher(new StringContains(message)))
代替
expectMessage(message)
您可以编写自定义 ExpectedException
或实用程序方法来包装代码。
截至 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
尽管这是一个非常古老的问题,并且可能前面提到的许多想法解决了许多问题,但我仍然想与解决我的问题的社区分享解决方案。
我发现问题出在一个名为“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));
这可能不是最好的解决方案,但我只想提一下,由于错误/未知的数据类型也可能引发异常。
我有一个 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-all 和 mockito-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 中,这允许检测到与依赖项分析工具可能存在的版本不兼容。当在项目中使用依赖管理工具时,这是更好的解决方案。
就我而言,我不得不从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'
对我有用的是从 junit 测试编译中排除 hamcrest 组。
这是我的 build.gradle 中的代码:
testCompile ('junit:junit:4.11') {
exclude group: 'org.hamcrest'
}
如果您正在运行 IntelliJ,您可能需要运行 gradle cleanIdea idea clean build
以再次检测依赖项。
我知道这不是最好的答案,但如果你不能让类路径工作,这是一个 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_();
}
对于 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>
不定期副业成功案例分享