12

私は TestNG と RESTeasy で本当に厄介な問題を経験しています。

RESTeasy フレームワークを使用して自身を公開する API クラスに対していくつかのテストを実行するクラスがあります。

ただし、maven (mvn test) でテストを実行すると、次の例外が発生します。

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)

このテストは、(RESTeasy から) Response オブジェクトを返す API オブジェクトのメソッドを呼び出すだけです。テスト フレームワークとして、私は TestNG を使用します。

試験方法

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

問題の説明

RESTeasy フレームワークは、RuntimeDelegate を別のクラス ローダーにロードするようです。ソース コードを見ると、RuntimeDelegate (126 行目) に次のメソッドがあります: RuntimeDelegate.java

したがって、エラーに関連する主なステートメントは instanceof チェックです。

if (!(delegate instanceof RuntimeDelegate))

デリゲート インスタンスのクラスローダーと RuntimeDelegate のクラスローダーを比較すると、次の出力が得られます。

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

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

もちろんこれが機能しないことは承知していますが、RESTeasy が MockClassLoader にロードされ、他のものにはロードされないのはなぜだろうかと思います。特に、テストされる TokenAPI をモックしていないためです。

奇妙な事実

奇妙なことに、IntelliJ からテストを実行すると (エラーを生成するメソッドを含む特定のクラスからすべてのテストを実行することのみを選択します)、実行されます。mvn test がmavenプロジェクトのすべてのテストを実行するという事実に何らかの形で関連しているようです(または少なくともそれは私が推測していることです)。

4

3 に答える 3

9

残念ながら、この問題が発生した理由はお伝えできませんが、この問題を回避する方法はお伝えできます。

問題は、PowerMockito がクラスパスをスキャンし、RESTeasy クラス (パッケージ 'javax.ws.*' 内にある) も追加したことでした。そのため、上記の RuntimeDelegate が PowerMockito クラスローダーによってロードされ、後で問題が発生しました。クラスが別のクラスローダのクラスと比較されました。

この問題を回避するには、PowerMockito にクラスのスキャン時に javax.ws パッケージを無視するように指示します。

@PowerMockIgnore({"javax.ws.*"})
于 2012-01-30T06:48:15.597 に答える