静态导入JUnitMatchers.containsString但不起作用但不是CoreMatchers.containsString

时间:2017-07-10 16:37:29

标签: junit hamcrest

我有一个相当庞大的代码库。其中一个测试类是使用import语句,该语句在编译期间因以下静态导入而失败。它在import语句以及对constainsString()的实际调用的位置失败。

import static org.hamcrest.CoreMatchers.containsString;

确切的错误如下:

[ERROR] MyClassName:[...] error: cannot find symbol
[ERROR] symbol:   method containsString(String)
[ERROR] location: class MyClassName

将上述静态导入更改为JUnitMatchers.containsString可解决此问题:

import static org.junit.matchers.JUnitMatchers.containsString;

我的有效pom.xml具有以下相关依赖项:

junit:jUnit:4.11
org.hamcrest:hamcrest-all:1.1
org.mockito:mockito-all:1.9.5

所以,问题确实是

  1. 为什么JUnitMatchers.containsString成功,实际上它被弃用而不支持CoreMatchers.containsString?
  2. 如果它拿起任何库的错误版本,我们怎么能让maven使用正确的版本?

1 个答案:

答案 0 :(得分:2)

Hamcrest 1.1没有containsString方法。无法找到源代码(显然,根据comment on this commit,之前正在生成类),但我们可以使用反编译的类:

public class CoreMatchers {
    public static <T> Matcher<T> is(Matcher<T> matcher) {
        return Is.is(matcher);
    }

    public static <T> Matcher<T> is(T value) {
        return Is.is(value);
    }

    public static Matcher<Object> is(Class<?> type) {
        return Is.is(type);
    }

    public static <T> Matcher<T> not(Matcher<T> matcher) {
        return IsNot.not(matcher);
    }

    public static <T> Matcher<T> not(T value) {
        return IsNot.not(value);
    }

    public static <T> Matcher<T> equalTo(T operand) {
        return IsEqual.equalTo(operand);
    }

    public static Matcher<Object> instanceOf(Class<?> type) {
        return IsInstanceOf.instanceOf(type);
    }

    public static <T> Matcher<T> allOf(Matcher... matchers) {
        return AllOf.allOf(matchers);
    }

    public static <T> Matcher<T> allOf(Iterable<Matcher<? extends T>> matchers) {
        return AllOf.allOf(matchers);
    }

    public static <T> Matcher<T> anyOf(Matcher... matchers) {
        return AnyOf.anyOf(matchers);
    }

    public static <T> Matcher<T> anyOf(Iterable<Matcher<? extends T>> matchers) {
        return AnyOf.anyOf(matchers);
    }

    public static <T> Matcher<T> sameInstance(T object) {
        return IsSame.sameInstance(object);
    }

    public static <T> Matcher<T> anything() {
        return IsAnything.anything();
    }

    public static <T> Matcher<T> anything(String description) {
        return IsAnything.anything(description);
    }

    public static <T> Matcher<T> any(Class<T> type) {
        return IsAnything.any(type);
    }

    public static <T> Matcher<T> nullValue() {
        return IsNull.nullValue();
    }

    public static <T> Matcher<T> nullValue(Class<T> type) {
        return IsNull.nullValue(type);
    }

    public static <T> Matcher<T> notNullValue() {
        return IsNull.notNullValue();
    }

    public static <T> Matcher<T> notNullValue(Class<T> type) {
        return IsNull.notNullValue(type);
    }

    public static <T> Matcher<T> describedAs(String description, Matcher<T> matcher, Object... values) {
        return DescribedAs.describedAs(description, matcher, values);
    }
}

无法在中央仓库中找到1.2版本,but 1.3确实定义了该方法(以及其他一些方法)。

JUnit 4.11(以及4.12)已经引用了Hamcrest 1.3,但mockito-1.9.5 references v1.1(滚动到依赖项)。您还可以通过运行mvn dependency:tree

来查看此内容
[INFO] \- org.mockito:mockito-core:jar:1.9.5:compile
[INFO]    +- org.hamcrest:hamcrest-core:jar:1.1:compile
[INFO]    \- org.objenesis:objenesis:jar:1.0:compile

---------------

[INFO] +- junit:junit:jar:4.11:compile
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:compile

在没有看到实际的pom的情况下,我无法说出如何,但不知何故v1.1优先于1.3,要么显式,要么在junit之前在你的pom中声明mockito。因此,您可以尝试在您的pom中交换junit和mockito顺序,或者直接将Hamcrest 1.3定义为覆盖传递版本:

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>