Tôi thực sự gặp phải một vấn đề thực sự khó chịu với TestNG và RESTeasy.java.lang.LinkageError: ClassCastException
Tôi có một lớp chạy một số thử nghiệm đối với lớp API sử dụng khung RESTeasy để lộ chính nó.
Tuy nhiên nếu tôi để cho chạy thử với maven (thử nghiệm mvn), sau đó tôi nhận được ngoại lệ sau đây:
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)
Xét nghiệm này không gì hơn là gọi một phương thức của obejct API trả về một đối tượng Response (từ RESTeasy). Là khung kiểm thử, tôi sử dụng TestNG.
Phương pháp thử
@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"));
}
Issue Mô tả
Dường như khuôn khổ RESTeasy tải RuntimeDelegate trong một bộ nạp lớp khác nhau. Nếu tôi xem xét mã nguồn, thì có phương thức sau tại RuntimeDelegate (bao gồm dòng 126): RuntimeDelegate.java.
Vì vậy, các tuyên bố chính có liên quan đến lỗi này là việc kiểm tra instanceof:
if (!(delegate instanceof RuntimeDelegate))
Nếu tôi kiểm tra classloader của thể hiện ủy nhiệm vs classloader của RuntimeDelegate, sau đó tôi nhận được đầu ra sau đây:
delegate.getClass().getClassLoader() -> [email protected]
RuntimeDelegate.class.getClassLoader() -> [email protected]
Tôi biết rằng điều này tất nhiên không hiệu quả nhưng tôi tự hỏi tại sao các công cụ RESTeasy được tải trong MockClassLoader chứ không phải trong một MockClassLoader khác. Đặc biệt là tôi không chế nhạo TokenAPI được kiểm tra.
kiện Strange
Điều kỳ lạ là, khi tôi chạy thử nghiệm ra khỏi IntelliJ (tôi chỉ chọn để chạy tất cả các bài kiểm tra từ lớp trao, trong đó có phương pháp nào tạo ra lỗi), sau đó nó chạy qua. Dường như nó là bằng cách nào đó liên quan đến thực tế là thử nghiệm mvn chạy tất cả các bài kiểm tra từ dự án maven (hoặc ít nhất đó là những gì tôi đoán).
Ít nhất tôi đã tìm ra cách để chạy thử nghiệm lần nữa: Một trong các thử nghiệm sử dụng PowerMockito và như đã nêu trong trình tải lớp ở trên, bằng cách nào đó PowerMockito đã tải các lớp bên dưới gói jagax.ws. Để vô hiệu hóa PowerMockito để tải các lớp học, tôi đã thêm gói javax.ws vào chú thích PowerMockitoIgnore: ({ "javax.ws *"}) @PowerMockIgnore Tôi vẫn không nhận được lý do tại sao kiểm tra không sử dụng trình nạp lớp được cung cấp bởi PowerMockito. Điều này có liên quan đến TestNG không? – rit
Hi rit, nó thực sự phụ thuộc vào những lớp học được nạp trước bởi bộ nạp lớp hệ thống trước hay không. Mã của bạn chắc chắn tham khảo một số lớp JAX-WS, mà có thể tham khảo các classe khác trong JAX-WS. JVM thực hiện liên kết sau để tránh tải không cần thiết khi khởi động. Vì vậy, khi các lớp này được sử dụng lần đầu tiên chúng được nạp bởi trình nạp lớp PowerMock, nhưng khi RESTeasy được khởi động, nó được nạp bằng cách sử dụng trình nạp lớp hệ thống, sau đó loại được so sánh (instanceof) chúng khác nhau, vì chúng được nạp khác nhau bộ nạp lớp. Giải pháp của bạn là giải pháp phù hợp. – Brice
Nếu giải pháp của bạn hoạt động và là giải pháp phù hợp, bạn có thể trả lời câu hỏi của riêng mình. – Luciano