PowerMock java.lang.ClassCastException:sun.net.www.protocol.https.HttpsURLConnectionImpl无法转换为javax.net.ssl.HttpsURLConnection [英] PowerMock java.lang.ClassCastException: sun.net.www.protocol.https.HttpsURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection

查看:1392
本文介绍了PowerMock java.lang.ClassCastException:sun.net.www.protocol.https.HttpsURLConnectionImpl无法转换为javax.net.ssl.HttpsURLConnection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基于 StackExchange答案创建了一个模拟 HttpsURLConnection

I created a mock HttpsURLConnection based on an StackExchange answer:

import java.net.URL;
import javax.net.ssl.HttpsURLConnection;

...

@RunWith(PowerMockRunner.class)
public class DialogTest {
    public void mockHttpsUrlConnectionExample() throws Exception
    {
        URL mockUrl = PowerMockito.mock(URL.class);
        PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockUrl);
        HttpsURLConnection mockUrlConnection = PowerMockito.mock(HttpsURLConnection.class);
        PowerMockito.when(mockUrl.openConnection()).thenReturn(mockUrlConnection);
        PowerMockito.when(mockUrlConnection.getResponseCode()).thenReturn(200);

        // Create and call my objects ...

    }
}

但是,当我使用它时,出现强制转换例外:

However, when I use it, I'm seeing a cast exception:

java.lang.ClassCastException: sun.net.www.protocol.https.HttpsURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection

问题出在此代码中:

import java.net.URL;
import javax.net.ssl.HttpsURLConnection;

...

private Boolean sendRequest(String endpoint, JSONObject requestData, Boolean throwOnAuthException) throws JSONException, IOException {
    this.responseData = null;

    try {
        String serviceURI = getServiceURI();
        String dialogUri = String.format("%s%s", serviceURI, endpoint);
        URL url = new URL(dialogUri);

        // Exception source is this cast
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();

但是,当我查看源代码时,看到的是 sun。 net.www.protocol.https.HttpsURLConnectionImpl 实现 javax.net.ssl.HttpsURLConnection

However, when I look at the source code, I see that sun.net.www.protocol.https.HttpsURLConnectionImpl implements javax.net.ssl.HttpsURLConnection

关于如何解决此问题的任何建议?

Any suggestions on how to remedy this problem?

推荐答案

常规类加载器与PowerMock的冲突

PowerMock的缺点是使用自定义类加载器。该类加载器可以以与默认类加载器不兼容的方式修改类型签名。

The drawback to PowerMock is the use of a custom class loader. This class loader can modify type signatures in a way that is incompatible with the default class loader.

在某些情况下,通过反射实例化将导致使用默认的类加载器来加载类型。由于使用了不同的签名,该类加载器将不知道PowerMock已经加载了一个类型。结果可能是应该实现转换类型的
对象的转换错误。

In certain circumstances, instantiation by reflection will cause the default class loader to be used to load a type. That class loader will not know that a type has already be loaded by PowerMock, because of the use of different signatures. The result can be casting errors for objects that should implement the cast type.

为避免此问题,请先停止PowerMock加载 javax.net.ssl.HttpsURLConnection

To avoid this problem, first stop PowerMock from loading javax.net.ssl.HttpsURLConnection

为防止强制转换异常,请使用确保javax.net.ssl。 HttpsURLConnection仅由一个类加载器加载。由于无法停止使用常规类加载器,因此最好的方法是使用 @PowerMockIgnore 注释阻止PowerMock加载器起作用。例如。

To prevent the cast exception, use ensure javax.net.ssl.HttpsURLConnection is only loaded by one class loader. Since I cannot stop the regular class loader from being used, the best approach is to stop the PowerMock loader from acting using the @PowerMockIgnore annotation. E.g.

@PowerMockIgnore({"javax.net.ssl.*"})
@PrepareForTest(android.util.Log.class)
public class DialogTest {
...

侧面效果是PowerMock不再能够提供其版本的 HttpsURLConnection

The side effect is that PowerMock is no longer able to provide it's version of HttpsURLConnection

接下来,公开HttpsURLConnection的构造,并替换一个模拟对象

为HttpsURLConnection引入工厂。例如。

Introduce a factory for HttpsURLConnection. E.g.

public class HttpsUrlConnectionProvider {
    public HttpsURLConnection getHttpsURLConnection(String dialogUri) throws IOException {
        URL url = new URL(dialogUri);
        return (HttpsURLConnection) url.openConnection();
    }
}

创建用于HTTP请求的HttpsURLConnection对象的模拟例如,

Create a mock of the HttpsURLConnection object used for HTTP request E.g.

final HttpsURLConnection mockUrlConnection = PowerMockito.mock(HttpsURLConnection.class);
PowerMockito.when(mockUrlConnection, "getResponseCode").thenReturn(200);
PowerMockito.when(mockUrlConnection, "getOutputStream").thenReturn(outputStream);

// Replace the HttpsURLConnection factory with one that returns our mock HttpsURLConnection
HttpsUrlConnectionProvider mockConnFactory = new HttpsUrlConnectionProvider() {
    public HttpsURLConnection getHttpsURLConnection(String dialogUri) throws
            IOException {
       return mockUrlConnection;
    }
};
dialog.setHttpsUrlConnectionProvider(mockConnFactory);

这篇关于PowerMock java.lang.ClassCastException:sun.net.www.protocol.https.HttpsURLConnectionImpl无法转换为javax.net.ssl.HttpsURLConnection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆