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.
InformationsquelleAutor rit | 2012-01-11
Schreibe einen Kommentar