Получение «NoSuchMethodError: org.hamcrest.Matcher.describeMismatch» при запуске теста в IntelliJ 10.5 - PullRequest
217 голосов
/ 24 октября 2011

Я использую 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, единственные jamcrest jar в моем classpath - это 1.3.RC2.

Использует ли IntelliJ IDEA собственную копию JUnit или Hamcrest?

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

Ответы [ 12 ]

262 голосов
/ 24 октября 2011

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

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

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

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

159 голосов
/ 24 мая 2013

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

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

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

mvn dependency:tree -Dscope=test
26 голосов
/ 21 ноября 2014

Следующее должно быть наиболее правильным сегодня.Обратите внимание, что junit 4.11 зависит от ядра Hamcrest, поэтому вам не нужно указывать, что 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>
13 голосов
/ 13 апреля 2014

Это сработало для меня после небольшой попытки

<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>
4 голосов
/ 06 февраля 2015

Попробуйте

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

вместо

expectMessage(message)

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

2 голосов
/ 22 мая 2017

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

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

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

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

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

long ID = ...;

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

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

long ID = ...;

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

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

0 голосов
/ 09 февраля 2019

В моем случае мне пришлось исключить старый хемкрест из 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>
0 голосов
/ 06 января 2019

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

...