java.lang.LinkageError: ClassCastException

Je fais l'expérience d'un vraiment problème ennuyeux avec TestNG et RESTeasy.

J'ai une classe qui gère plusieurs tests à l'encontre d'une classe de l'API qui utilise le RESTeasy-cadre pour exposer lui-même.

Cependant si je laisse l'essai avec maven (mvn test), puis-je obtenir de l'exception suivante:

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)

Le test n'est rien de plus que d'appeler une méthode de l'API obejct qui retourne un objet Response (à partir de RESTeasy). Comme framework de test je ne l'utilisation de TestNG.

Méthode D'Essai

@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"));
}

Description Du Problème

Il ressemble à la RESTeasy cadre charge le RuntimeDelegate dans un autre chargeur de classe. Si je prends un coup d'oeil au code source, puis il y a la méthode suivante à la RuntimeDelegate (qui couvre la ligne 126): RuntimeDelegate.java.

De sorte que le message principal qui est lié à l'erreur est la instanceof vérifier:

if (!(delegate instanceof RuntimeDelegate))

Si je vérifie le chargeur de classe de l'instance de délégué vs le chargeur de classe de la RuntimeDelegate, puis-je obtenir la sortie suivante:

delegate.getClass().getClassLoader() -> org.powermock.core.classloader.MockClassLoader@31e46a68

RuntimeDelegate.class.getClassLoader() -> sun.misc.Launcher$AppClassLoader@3c0fabe9

Je suis conscient de que bien sûr, cela ne fonctionne pas, mais je me demande pourquoi le RESTeasy truc est chargé dans le MockClassLoader et pas dans l'autre. Surtout que je n'ai pas se moquer de la TokenAPI qui est testé.

Faits Étranges

La chose étrange est que lorsque j'exécute les tests de IntelliJ (je choisis uniquement pour exécuter tous les tests de la classe qui contient la méthode qui produit le message d'erreur), alors qu'il traverse. On dirait qu'il est en quelque sorte lié au fait que mvn test s'exécute tous les tests du projet maven (ou du moins c'est ce que je suppose).

Au moins j'ai compris maintenant comment obtenir les tests de nouveau: Un des tests utilise PowerMockito et comme indiqué dans le chargeur de classe ci-dessus, en quelque sorte PowerMockito chargé des classes sous le paquet jagax.ws. Pour désactiver PowerMockito pour charger les classes, j'ai ajouté les javax.ws colis à l'PowerMockitoIgnore annotation: @PowerMockIgnore({"javax.ws.*"}) Je ne comprends pas pourquoi le test qui échoue utilise le chargeur de classe fourni par PowerMockito. Est-ce lié à TestNG?
Salut rit, cela dépend si ces classes ont été chargées d'abord par le système de chargeur de classe avant ou pas. Votre code certainement référence à certains JAX-WS classes, qui peut faire référence à d'autres classe de JAX-WS. La JVM ne les reliant plus tard pour éviter la charge au moment du démarrage. Ainsi, lorsque ces classes sont utilisées pour la première fois, ils sont chargés par le PowerMock chargeur de classe, mais quand RESTeasy a commencé, il est chargé en utilisant le système de chargeur de classe, puis plus tard de type sont comparées (le instanceof) ils sont différents, parce qu'ils ont été chargés dans le chargeur de classes différentes. Votre solution est la bonne.
Si votre solution est la bonne, vous pouvez répondre à votre propre question.
mvn test peut être demandé à la "fourchette" des essais par la voie.

OriginalL'auteur rit | 2012-01-11