Получение "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" при запуске теста в 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 в моем пути к классам - 1.3.RC2.

Является ли IntelliJ IDEA собственной копией JUnit или Hamcrest?

Как выполнить вывод CLASSPATH во время выполнения, который использует IntelliJ?

Ответ 1

Проблема заключалась в том, что использовался неправильный класс hamcrest.Matcher, а не hamcrest.MatcherAssert. Это было втянуто из зависимости junit-4.8, которую указала одна из моих зависимостей.

Чтобы узнать, какие зависимости (и версии) включены из источника во время тестирования, выполните:

mvn dependency:tree -Dscope=test

Ответ 2

Убедитесь, что баннер hamcrest выше в порядке импорта, чем ваш баннер JUnit.

JUnit поставляется со своим классом org.hamcrest.Matcher, который, вероятно, используется вместо него.

Вы также можете загрузить и использовать junit-dep-4.10.jar, который является JUnit без классов hamcrest.

В mockito также есть классы hamcrest, поэтому вам может потребоваться переместить\переупорядочить его также

Ответ 3

Эта проблема возникает также, когда у вас есть 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>

Ответ 4

Сегодня самое правильное. Примечание. 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>

Ответ 5

Это сработало для меня после битвы

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

Ответ 6

Try

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

вместо

expectMessage(message)

Вы можете написать собственный ExpectedException или служебный метод для завершения кода.

Ответ 7

Я знаю, что это старый поток, но для решения этой проблемы я добавил следующее в мои файлы 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'

Ответ 8

Несмотря на то, что это очень старый вопрос и, вероятно, многие из вышеперечисленных идей решают многие проблемы, Я все еще хочу поделиться решением с сообществом, которое исправило мою проблему.

Я обнаружил, что проблема была функцией, называемой "hasItem" который я использовал, чтобы проверить, содержит ли JSON-Array определенный элемент. В моем случае я проверил значение типа Long.

И это привело к проблеме.

Как-то, у Matches есть проблемы со значениями типа Long. (Я не использую JUnit или Rest-Assured так сильно, как idk. Именно поэтому, но я думаю, что возвращенные JSON-данные содержат только целые числа.)

Итак, что я сделал, чтобы исправить эту проблему, было следующее. Вместо использования:

long ID = ...;

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

вам просто нужно отправить в Integer. Итак, рабочий код выглядел так:

long ID = ...;

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

Это, вероятно, не лучшее решение, но я просто хотел упомянуть, что исключение также может быть выбрано из-за неправильных/неизвестных типов данных.

Ответ 9

Что сработало для меня, было исключение группы hamcrest из компиляции теста junit.

Вот код из моего build.gradle:

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

Если вы используете IntelliJ, вам может понадобиться запустить gradle cleanIdea idea clean build, чтобы снова определить зависимости.

Ответ 10

Я знаю, что это не лучший ответ, но если вы не можете получить работу с классом, это решение плана B.

В моем тестовом пути я добавил следующий интерфейс с реализацией по умолчанию для метода describeMismatch.

package org.hamcrest;

/**
 * PATCH because there 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_();
}

Ответ 11

У меня есть проект 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, чтобы просто положить его на classpath. Это может выглядеть странно, но, пожалуйста, помните, что разработка Mockito началась во времена, когда чистый Ant (без управления зависимостями) был самой популярной сборкой система для проектов Java и все внешние JAR файлы, требуемые проект (т.е. наши проекты и их зависимости) имели загружаться вручную и указываться в сценарии сборки.

С другой стороны, mockito-core.jar - это просто классы Mockito (также с переупакованы ASM и CGLIB). При использовании с Maven или Gradle требуется зависимости (Hamcrest и Objenesis) управляются этими инструментами (загружается автоматически и ставится на тестовый путь к классам). Это позволяет переопределить используемые версии (например, если наши проекты не используют никогда, но версия с обратной совместимостью), но что важнее зависимости не скрыты внутри mockito-all.jar, что позволяет обнаружена возможная несовместимость версий с анализом зависимостей инструменты. Это гораздо лучшее решение, когда средство управления зависимостями используется в проекте.

Ответ 12

В моем случае мне пришлось исключить старый подколенный сухожилий из junit-vintage:

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

Ответ 13

Это сработало для меня. Не нужно ничего исключать. Я просто использовал 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'