[FIXED] Android Instrumental test – SSLHandshakeException when using OkHttp MockServer.useHttps(…)

Issue

I am trying to test and REST API with OkHttps mock server. Because of anroid limitations (no clear text http request allowed in newer android versions) I need to user server.useHttps(...). I tried it with the default 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)
    }

Running the instrumental test throws following excepiton:

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)

I already did a lot of research but I haven’t found any similar blogs.
Thankful for any advice or documentation links.

Solution

Instead of using server.useHttps, you can simply try creating a network security config, whitelist localhost and add it to your app.

First, create a network_security_config.xml and put it into your app’s res/xml folder

<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>

Then add it to your app’s manifest

<?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

Answered By – Van Linh Nguyen

Answer Checked By – Clifford M. (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published