maven - test - NoSuchMethodError con Hamcrest 1.3 y JUnit 4.11
maven-surefire-plugin maven (8)
Otra instancia del NoSuchMethodError
para la combinación JUnit & Hamcrest. Código ofensivo:
assertThat(dirReader.document(0).getFields(), hasItem(
new FeatureMatcher<IndexableField, String>(equalTo("Patisnummer"), "Field key", "Field key") {
@Override
protected String featureValueOf(IndexableField actual) {
return actual.name();
} } ));
Líneas comentadas 152-157 en IndexerTest.java (commit ac72ce )
Causa un NoSuchMethodError (vea http://db.tt/qkkkTE78 para obtener un resultado completo):
java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V
at org.hamcrest.FeatureMatcher.matchesSafely(FeatureMatcher.java:43)
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:55)
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:25)
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:14)
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:55)
at org.junit.Assert.assertThat(Assert.java:770)
at org.junit.Assert.assertThat(Assert.java:736)
at indexer.IndexerTest.testIndexContainsField(IndexerTest.java:152)
La puesta en marcha:
- JUnit 4.11
- Hamcrest 1.3
- Usando el plugin surefire de Maven (versión 2.14), que usa su JUnitCoreProvider
- Java 7 (OpenJDK)
- Ver pom (commit ac72ce )
Fondo:
Un NoSuchMethodError
es causado por clases (compiladas) que llaman a métodos no existentes. El caso específico de describeMismatch
y la combinación JUnit + Hamcrest a menudo es causado por una incompatibilidad entre las clases de Hamcrest incluidas en JUnit y las versiones de esas clases en la biblioteca de Hamcrest.
Intenta resolver el NoSuchMethodError:
The pom contiene una dependencia explícita en Hamcrest-library 1.3, Hamcrest-core 1.3 y JUnit 4.11, (en ese orden) según lo sugerido por Garrett Hall en answer a Getting "NoSuchMethodError: org.hamcrest.Matcher.describeMismatch" al ejecutar la prueba en IntelliJ 10.5
De acuerdo con la documentación de JUnit, la dependencia de JUnit 4.11 Maven ya no incluye clases compiladas de Hamcrest, sino que tiene una dependencia de Hamcrest-core 1.3; por lo que el
NoSuchMethodError
no debería ocurrir.Comprobando el árbol de dependencia con la
mvn dependency:tree
como lo sugirió Dan en answer a la declaración junit y hamcrest muestra las dependencias explícitas en Hamcrest 1.3 y JUnit 4.11 y ninguna otra dependencia de esos archivos (ver http://db.tt/C2OfTDJB para el salida completa).En otra prueba, se evitó
NoSuchMethodError
al usar:assertThat( "Zylab detector not available", d.getDetectors(), hasItem(Matchers.<Detector>instanceOf(ZylabMetadataXmlDetector.class)));
En las líneas 120-123 de IndexerTest.java (commit ac72ce ) en lugar de lo más obvio:
assertThat( "Zylab detector not available", d.getDetectors(), hasItem(isA(ZylabMetadataDetector.class));
No estoy seguro si el parámetro de tipo explícito
<Detector>
, utilizandoinstanceOf
lugar deisA
, la referencia explícita a Hamcrest''sMatchers
, o una combinación de aquellos que evitaronNoSuchMethodException
; después de juguetear e intentar diferentes cosas, funcionó.El uso de parámetros de tipo explícito no resolvió / evitó el error.
Usar una clase derivada de
BaseMatcher
lugar deFeatureMatcher
no resolvió / evitó el error.
Ideas cómo arreglar el NoSuchMethodError
?
Este blog me ayudó a solucionar el mismo problema:
Dentro de las dependencias de Mockito y Junit, el autor agregó excluye:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
Lo que funcionó para mí fue reordenar dependencias. En vez de ir a mockito, junit, tuve que poner junit, mockito.
Mockito 1.9.5 usa hamcrest 1.1, que es incompatible y causa problemas.
Para un proyecto con Gradle
como herramienta de compilación:
testCompile("junit:junit:4.11") {
exclude group: ''org.hamcrest'', module: ''hamcrest-core''
exclude group: ''org.hamcrest'', module: ''hamcrest-library''
}
testCompile group: ''org.hamcrest'', name: ''hamcrest-core'', version: ''1.3''
testCompile group: ''org.hamcrest'', name: ''hamcrest-library'', version: ''1.3''
Quizás uno de esos otros JAR tiene versiones anteriores de Hamcrest''s Matcher
o BaseMatcher
. Aquí hay una lista de JAR que incluye este último, aunque no tengo idea de qué tan completo es ese sitio. ¿Hay algún complemento Maven que le muestre todas las dependencias que incluyen una clase similar al árbol de dependencias?
Si está usando Eclipse: Para mí, en eclipse-> propiedades del proyecto-> compilación Java La ruta moviendo mockito-all-1.9.5.jar al final de la lista ''Ordenar y Exportar'' hizo el truco. Justo encima tengo junit-4.11.jar y encima ese hamcrest-core-1.3.jar
Si está utilizando Eclipse, la herramienta "Tipo abierto" (CTRL + MAYÚS + T) puede ayudarlo a encontrar el paquete problemático. Simplemente busque el nombre de la clase (por ej., Descripción), las múltiples ocurrencias de la misma clase de diferentes JAR son banderas rojas.
Usando sugerencia y ¿Cómo divido una cadena en un delimitador en Bash? dio como resultado el siguiente script bash:
( IFS=":"; for i in `mvn dependency:build-classpath | grep -v ''/[INFO/]''`; do jar tf $i | awk "{print /"$i//t/" /$1}"; done | grep Matcher )
(en línea en http://www.kaspervandenberg.net/2013/scripts/findDependencyClass.sh )
Que encontró que la dependencia JGlobus-Core-2.0.4
tiene sus propias versiones de org.hamcrest.BaseMatcher
, org.hamcrest.CoreMatchers
y org.hamcrest.Matcher
.
Gradle
este problema de jar hell
problema en mi proyecto de Gradle
con el siguiente código:
testCompile (group: ''junit'', name: ''junit'', version: ''4+'') {
exclude group: ''org.hamcrest''
}
testCompile (''org.mockito:mockito-core:1+'') {
exclude group: ''org.hamcrest''
}
testCompile ''org.hamcrest:java-hamcrest:2.0.0.0''