java.lang.LinkageError: Classcastexception-Fehler
Ich tun, erleben Sie eine wirklich lästige problem mit TestNG und RESTeasy.
Ich habe eine Klasse, führt mehrere tests gegen eine API-Klasse verwendet das RESTeasy-framework zu entlarven sich selbst.
Jedoch wenn ich lasse den test laufen mit maven (mvn test), dann bekomme ich die folgende exception:
java.lang.LinkageError: ClassCastException: attempting to castjar:file:/C:/Users/rit/.m2/repository/org/jboss/resteasy/jaxrs-api/2.3.0.GA/jaxrs-api-2.3.0.GA.jar!/javax/ws/rs/ext/RuntimeDelegate.classtojar:file:/C:/Users/rit/.m2/repository/org/jboss/resteasy/jaxrs-api/2.3.0.GA/jaxrs-api-2.3.0.GA.jar!/javax/ws/rs/ext/RuntimeDelegate.class
at javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:126)
at javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:96)
at javax.ws.rs.core.Response$ResponseBuilder.newInstance(Response.java:394)
at javax.ws.rs.core.Response.status(Response.java:116)
at javax.ws.rs.core.Response.status(Response.java:130)
at com.pd.api.TokenAPI_V1.validateAccessToken(TokenAPI_V1.java:141)
at com.test.pd.api.TokenAPI_V1Test.testIfValidAccessTokenReturnsCorrectHTTPHeadersWhenTokenIsNotFound(TokenAPI_V1Test.java:359)
Den test macht nichts anderes als der Aufruf einer Methode des API-Objekt liefert ein Response-Objekt (aus RESTeasy). Als Test-framework verwende ich TestNG.
Test Methode
@Test
public void testIfValidAccessTokenReturnsCorrectHTTPHeadersWhenTokenIsNotFound() throws InvalidAccessTokenException {
Mockito.when(tokenService.validateAccessToken(TestConstants.ACCESS_TOKEN)).thenThrow(new InvalidAccessTokenException());
Response response = tokenAPI_v1.validateAccessToken(TestConstants.ACCESS_TOKEN, TestConstants.USER_AGENT);
assert "no-store".equals(response.getMetadata().getFirst("Cache-Control"));
assert "no-cache".equals(response.getMetadata().getFirst("Pragma"));
}
Thema Beschreibung
Sieht es aus wie das RESTeasy-framework lädt die RuntimeDelegate in einem anderen class loader. Wenn ich einen Blick auf den Quellcode, dann gibt es die folgende Methode, bei der RuntimeDelegate (die Abdeckungen Linie 126): RuntimeDelegate.java.
So die zentrale Aussage, die im Zusammenhang mit der Fehlermeldung wird der instanceof-check:
if (!(delegate instanceof RuntimeDelegate))
Wenn ich den classloader des Delegaten-Instanz vs der classloader der RuntimeDelegate, dann bekomme ich die folgende Ausgabe:
delegate.getClass().getClassLoader() -> org.powermock.core.classloader.MockClassLoader@31e46a68
RuntimeDelegate.class.getClassLoader() -> sun.misc.Launcher$AppClassLoader@3c0fabe9
Ich bin mir bewusst, dass dies natürlich nicht funktioniert, aber ich Frage mich, warum die RESTeasy Zeug ist geladen in der MockClassLoader und nicht in die andere. Vor allem da ich don ' T mock the TokenAPI, die getestet wird.
Seltsamen Fakten
Das merkwürdige ist, dass ich beim ausführen dieser tests aus IntelliJ (ich wähle nur, um führen Sie alle tests aus der Klasse die die Methode enthält, die den Fehler erzeugt), dann läuft es durch. Wie es aussieht ist es irgendwie im Zusammenhang mit der Tatsache, dass mvn test führt alle tests aus der maven-Projekt (oder zumindest das ist, was ich vermute).
- Zumindest dachte ich jetzt raus, wie man die tests wieder laufen: Einer der tests verwendet PowerMockito und wie gesagt in der classloader oben, irgendwie PowerMockito lud die Klassen unterhalb der Paket jagax.ws. Deaktivieren PowerMockito zum laden der Klassen, die ich Hinzugefügt habe, die javax.ws-Paket, um die PowerMockitoIgnore annotation: @PowerMockIgnore({"javax.ws.*"}) Immer noch verstehe ich nicht, warum der test, der fehlschlägt, verwendet den classloader zur Verfügung gestellt von PowerMockito. Ist das mit TestNG?
- Hallo rit, die es eigentlich abhängt, ob jene Klassen geladen wurden zunächst von der system-classloader vor oder nicht. Dein code sicherlich einige Referenz JAX-WS-Klassen, die möglicherweise auf andere classe, die in JAX-WS. Die JVM stellt die Verknüpfung später zu vermeiden, die unnötige Last beim Start. Also, wenn diese Klassen werden verwendet, für das erste mal geladen sind, die von der PowerMock-classloader, aber wenn RESTeasy ist gestartet, es ist geladen mit dem system-classloader, dann später Art verglichen (die ein), Sie sind anders, weil Sie geladen wurden in verschiedenen classloader. Ihre Lösung ist die richtige.
- Wenn deine Lösung funktioniert und ist richtig, Sie können Ihre eigene Frage zu beantworten.
- mvn test kann angewiesen werden, die "Gabel" bei den tests durch die Art und Weise.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Leider kann ich Ihnen nicht sagen, warum das passiert ist, aber ich kann Ihnen sagen, wie man um dieses Problem.
Das problem war, dass PowerMockito gescannt tha-Klasse Weg und fügte auch die RESTeasy-Klassen (welche sich im package 'javax.ws.*'. HIERFÜR können die oben genannten RuntimeDelegate geladen wurde durch die PowerMockito classloader und verursacht später das Problem, dass die Klasse im Vergleich gegen ein von einem anderen classloader.
Zu bekommen, um dieses Problem sagen PowerMockito zu ignorieren, die javax.ws-Paket beim Scannen für die Klassen:
Ich Stand vor dem gleichen Problem bei der Nutzung meiner Anwendung auf JBoss v6.1 - irgendwie verstanden, dass das problem war durch die gleiche package-Struktur RuntimeDelegate.class innerhalb jesrey-core und jboss' jaxrs-api-jar -
Unten ist meine pom.xml
Nachdem mein Krieg Bereitstellung auf JBoss, nur entfernt resteasy.deployer-Ordner von jboss " server\default\Anwender-Ordner. Lief meine Bewerbung und es hat geklappt.
Ich würde mich freuen, wenn jemand erklären, warum dieser Fehler kam aufgelöst auf diese Weise? (Ich denke, JBoss' hat unnötig geliefert mit resteasy.Anwender Gläser, wenn die Entwickler könnten auch die Gläser, die auf Ihre eigenen in Ihre Anwendungen) - Nicht um zu verbergen, dass ich versuchte, bereitstellen von meinem Krieg auf Tomcat und es funktionierte reibungslos.