Android 仪器测试 - 使用 OkHttp 时出现 SSLHandshakeException MockServer.useHttps(...)
Android Instrumental test - SSLHandshakeException when using OkHttp MockServer.useHttps(...)
我正在尝试使用 OkHttps 模拟服务器进行测试和 REST API。由于 anroid 的限制(较新的 android 版本不允许明文 http 请求),我需要用户 server.useHttps(...)
。我用默认的 SSLSocketFactory
.
试了一下
class RetrofitIntegrationTest {
private lateinit var server: MockWebServer
private lateinit var retrofit: Retrofit
private lateinit var service: InstanceApi
@Before
fun setUp() {
server = MockWebServer()
server.useHttps(SSLSocketFactory.getDefault() as SSLSocketFactory, false)
server.start()
retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create())
.baseUrl(server.url("/"))
.build()
service = retrofit
.create(InstanceApi::class.java)
}
@After
fun teardown() {
server.shutdown()
}
@Test
fun testCompleteIntegration() = runBlocking {
server.enqueue(
MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(
"{ test: 'test' } "
)
)
Timber.i(retrofit.baseUrl().toString())
val response = service.apiInfo()
assertEquals(15, response.body()?.version)
}
运行 仪器测试抛出以下异常:
E/TestRunner: javax.net.ssl.SSLHandshakeException: connection closed
at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:362)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:240)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:217)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
我已经做了很多研究,但还没有找到任何类似的博客。
感谢您提供任何建议或文档链接。
除了使用 server.useHttps
,您还可以简单地尝试创建一个网络安全配置,将本地主机列入白名单并将其添加到您的应用中。
首先,创建一个 network_security_config.xml 并将其放入应用的 res/xml 文件夹中
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
<domain includeSubdomains="true">127.0.0.1</domain>
</domain-config>
</network-security-config>
然后将其添加到您应用的清单中
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
https://developer.android.com/training/articles/security-config
我正在尝试使用 OkHttps 模拟服务器进行测试和 REST API。由于 anroid 的限制(较新的 android 版本不允许明文 http 请求),我需要用户 server.useHttps(...)
。我用默认的 SSLSocketFactory
.
class RetrofitIntegrationTest {
private lateinit var server: MockWebServer
private lateinit var retrofit: Retrofit
private lateinit var service: InstanceApi
@Before
fun setUp() {
server = MockWebServer()
server.useHttps(SSLSocketFactory.getDefault() as SSLSocketFactory, false)
server.start()
retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create())
.baseUrl(server.url("/"))
.build()
service = retrofit
.create(InstanceApi::class.java)
}
@After
fun teardown() {
server.shutdown()
}
@Test
fun testCompleteIntegration() = runBlocking {
server.enqueue(
MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(
"{ test: 'test' } "
)
)
Timber.i(retrofit.baseUrl().toString())
val response = service.apiInfo()
assertEquals(15, response.body()?.version)
}
运行 仪器测试抛出以下异常:
E/TestRunner: javax.net.ssl.SSLHandshakeException: connection closed
at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:362)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:240)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:217)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
我已经做了很多研究,但还没有找到任何类似的博客。 感谢您提供任何建议或文档链接。
除了使用 server.useHttps
,您还可以简单地尝试创建一个网络安全配置,将本地主机列入白名单并将其添加到您的应用中。
首先,创建一个 network_security_config.xml 并将其放入应用的 res/xml 文件夹中
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
<domain includeSubdomains="true">127.0.0.1</domain>
</domain-config>
</network-security-config>
然后将其添加到您应用的清单中
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
https://developer.android.com/training/articles/security-config