Отримання "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" під час запуску тесту в IntelliJ 10.5


233

Я використовую 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, єдина бачка з кремом в моєму класі - 1.3.RC2.

Чи IntelliJ IDEA використовує власну копію JUnit або Hamcrest?

Як вивести CLASSPATH часу виконання, який використовує IntelliJ?

Відповіді:


272

Переконайтесь, що сторона хом'яка вище на замовлення на імпорт, ніж ваша банка JUnit

JUnit має власний org.hamcrest.Matcherклас, який, ймовірно, використовується замість цього.

Ви можете також завантажити та використовувати junit-dep-4.10.jar, який є JUnit без класів hamcrest.

mockito також має в ньому класи hamcrest, тому вам може знадобитися також перемістити \ змінити порядок


1
ОП заявила, що вже використовує банку "-dep-". Але ви здогадуєтесь, що це використання класу Matcher з банку JUnit звучить правильно. Тож, мабуть, IDE використовує власну копію JUnit.
MatrixFrog

2
Я видалив копію IntelliJ junit.jar та junit-4.8.jar, встановив junit-dep-4.10.jar в lib / каталог IntelliJ, і проблема все ще виникає.
Ноель Яп

8
JUnit 4.11 сумісний із Hamcrest 1.3, а JUnit 4.10 сумісний із Hamcrest 1.1 search.maven.org/remotecontent?filepath=junit/junit-dep/4.10/…
Muthu

23
переконайтесь, що ви НЕ використовуєте mockito-all, а натомість mockito-core з виключенням hamcrest
Ulf Lindback

1
Це 19:33 в офісі. Я працюю над важливою особливістю, яку я повинен поставити перед тим, як вийти у відпустку, і це п’ятниця, я перебуваю в цьому відпустці наступного тижня !!!!!! Як, да чорт, я міг зараз отримати цю помилку !!!
Аделін

170

Ця проблема також виникає, коли у вас є макет-all на шляху вашого класу, який уже застарів.

По можливості просто включіть mockito-core .

Конфігурація 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>

2
Зокрема, як нові версії mockito включають hamcrest також з powermock!
Том Паркінсон

3
Це повинно бути макет-ядром замість макет-все?
користувач944849

3
Ви можете включити просто core, якщо вам це потрібно лише в темпі всіх, однак вищезазначене має працювати у всіх випадках. Порядок залежностей - важливий біт mvn 3 починається зверху в порядку пріоритетності.
Том Паркінсон,

3
НЕ слід включати mockito-all, оскільки він включає hamcrest 1.1, замість цього включайте mockito-core та виключайте з нього hancrest (що ви не можете зробити з усіх)
Ulf Lindback

1
Msgstr "Якщо можливо, просто включіть mockito-core." Гаразд, то чому тоді ця відповідь все ще використовує макет-все?
Стелс-рабин

60

Проблема полягала в тому, що використовувався неправильний hamcrest.Matcher, а не hamcrest.MatcherAssertкласний. Це втягувалось із залежності від 4,88 липня, яку одна із моїх залежностей вказувала.

Щоб побачити, які залежності (та версії) включені з джерела під час тестування, запустіть:

mvn dependency:tree -Dscope=test

5
У мене було те саме питання. Я використовував JUnit-dep та Hamcrest-core, але я був перелічений Powermock раніше в пам’яті, що призвело до включення JUnit до JUnit-dep та Hamcrest.
Джон Б

9
Також mockito-all включає деякі класи Hamcrest. Краще використовувати mockito-core та виключати залежність від молока.
Брамбо

3
Просто натрапили на таку саму проблему. Рішення було збільшено до версії 4.11, яка сумісна (тобто "містить класи з") з hamcrest 1.3
r3mbol

Для тих, де всі пропозиції не спрацювали також (порядок залежності, виключення, видалення заміни -allна -coreтощо): мені довелося змінити hamcrest назад до версії 1.1, і тепер все працює знову.
Фелікс

1
для мене він працював , коли я змінив свій імпорт в import static org.mockito.Matchers.anyString;зimport static org.mockito.ArgumentMatchers.anyString;
Shrikant Прабху

28

Наступне має бути найбільш правильним сьогодні. Зауважте, липень 4.11 залежить від hamcrest-core, тому вам не потрібно вказувати, що мокіто-все не можна використовувати, оскільки воно включає (не залежить від) 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>

3
Зауважте, що JUnit 4.12 тепер залежить від основної версії 1.3.
JeeBee

Виключення з mockito-allдопомогло мені, ні mockito-core. Також оголошує Хемкреста перед Мокіто у pom.xmlтворах.
Кирило

13

Це спрацювало для мене після того, як трохи боровся

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

Те саме для мене. Встановлення залежностей у цьому порядку допомагає Maven правильно вирішувати транзитивні депа. Чітко виключаючи хомкрест із макет-ядра чи макіто - все це може бути безпечніше, якщо хтось переупорядкує занурення у вашу пом.
Мат

4

Спробуйте

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

замість

expectMessage(message)

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


4

Я знаю, що це стара тема, але те, що вирішило проблему для мене, було додавання наступних даних до моїх файлів build.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'

1

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

Я виявив, що проблема полягає у функції під назвою "hasItem", яку я використовував, щоб перевірити, чи містить JSON-масив певний елемент чи ні. У моєму випадку я перевірив значення типу 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

Що працювало для мене, було виключення групи hamcrest із компіляції тесту з джуніту.

Ось код з мого build.gradle:

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

Якщо ви працюєте з IntelliJ, можливо, вам доведеться запустити, gradle cleanIdea idea clean buildщоб знову виявити залежності.


0

Я знаю, що це не найкраща відповідь, але якщо ви не можете змусити працювати класним шляхом, це рішення плану B.

На своєму тестовому класі я додав наступний інтерфейс із реалізацією за замовчуванням для методу writeMismatch.

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_();
}

0

У мене є проект 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 -все-в-mavengradle-проекти /

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


0

У моєму випадку мені довелося виключити старішу верхівку хутра з юні-урожаю:

<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

Це працювало для мене. Не потрібно нічого виключати. Я просто використовував 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'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.