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


当前回答

我有一个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-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 besides Mockito itself contains also (as of 1.9.5) two dependencies: Hamcrest and Objenesis (let’s omit repackaged ASM and CGLIB for a moment). The reason was to have everything what is needed inside an one JAR to just put it on a classpath. It can look strange, but please remember than Mockito development started in times when pure Ant (without dependency management) was the most popular build system for Java projects and the all external JARs required by a project (i.e. our project’s dependencies and their dependencies) had to be downloaded manually and specified in a build script. On the other hand mockito-core.jar is just Mockito classes (also with repackaged ASM and CGLIB). When using it with Maven or Gradle required dependencies (Hamcrest and Objenesis) are managed by those tools (downloaded automatically and put on a test classpath). It allows to override used versions (for example if our projects uses never, but backward compatible version), but what is more important those dependencies are not hidden inside mockito-all.jar what allows to detected possible version incompatibility with dependency analyze tools. This is much better solution when dependency managed tool is used in a project.

其他回答

Try

expect(new StringContains(message))

而不是

expectMessage(消息)

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

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

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

我发现问题出在一个叫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文件。 如上所述,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'

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

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