Set Up MockWebServer for Android UI Test: Fix Network Security Issue

A step-by-step guide using MockWebServer on Android Jetpack Compose UI tests to fix java.net.UnknownServiceException issue

When writing Android UI tests, you might run into this error,

java.net.UnknownServiceException: CLEARTEXT 
communication to localhost not permitted by network security policy

This happens because modern Android versions, since Android 9 (API level 28), enforce stricter network security policies, preventing unencrypted (HTTP) communication. The changes also affect MockWebServer which uses a Localhost connection to mock API responses in Android instrumentation tests.

In this article, I’ll show you how to properly set up the MockWebServer for Android UI tests and configure the app to bypass this network security restriction.

Before starting, make sure the MockWebServer dependency has been installed.

[versions]
okhttp = "4.12.0"

[libraries]
okhttp-mockwebserver = { group = "com.squareup.okhttp3", name = "mockwebserver", version.ref = "okhttp" }

There are 2 options to fix the issue,

  1. Use network security config
  2. Enable HTTPS on MockWebServer

Create network_security_config.xml file inside debug/res/xml/ directory and add the localhost domain there.




localhost
127.0.0.1

  • Make sure to create the file inside the debug directory, not main directory. So this network security bypass does not affect the production app.

Then register the network security config to the debug/AndroidManifest.xml.


...
android:networkSecurityConfig="@xml/network_security_config">
...

  • Again, make sure to register the config to debug variant AndroidManifext.xml, so this network security bypass does not affect the production app.
Network security config setup

Install OkHttp-TLS dependency.

[versions]
okhttp = "4.12.0"

[libraries]
okhttp-tls = { group = "com.squareup.okhttp3", name = "okhttp-tls", version.ref = "okhttp" }

Create an SSL certificate using HeltCertificate.

val heldCertificate = HeldCertificate.Builder()
.commonName("localhost")
.addSubjectAlternativeName("localhost")
.build()
val certificates = HandshakeCertificates.Builder()
.heldCertificate(heldCertificate)
.addTrustedCertificate(heldCertificate.certificate)
.build()

Set up the MockWebServer with HTTPS.

MockWebServer().apply {
// enable https on mockwebserver
// use the HandshakeCertificates created above
useHttps(certificates.sslSocketFactory(), false)
}

Update the OkHttpClient to trust the certificate.

val okHttpClient = OkHttpClient.Builder()
// use the HandsakeCertificates created above
.sslSocketFactory(
certificates.sslSocketFactory(),
certificates.trustManager
)
.build()

Then set the OkHttpClient to the Retrofit and update the base URL with the MockWebServer URL.

val retrofit = Retrofit.Builder()
// change the base url with the one from mockwebserver
.baseUrl(mockWebServer.url("/").toString())
// set the okHttpClient
.client(okHttpClient)
.build()

Option 1: Using network security config in debug variant

  • ✅ Fast and simple to implement.
  • ✅ No need to modify API clients (OkHttp and Retrofit).
  • ❌ Not a real-world simulation, because production apps should use HTTPS.
  • ❌ Potential risk if misconfigured (eg. accidentally included in the production app).
  • ❌ Only works for the domain registered in the network security config.

Option 2: Enabling HTTPS on MockWebServer

  • ✅ More secure, aligns with the production app behavior.
  • ✅ Mimics real-world HTTPS usage, ensuring better test coverage.
  • ✅ No need to modify the app’s security policies.
  • ❌ More complex setup (requires setting up a self-signed certificate).
  • ❌ Requires modifying the API client (OkHttp needs to trust the self-signed certificate).
  • ❌ Can introduce flakiness if SSL setup is not handled correctly.

Enabling HTTPS on MockWebServer more complex to set up, especially if you are using dependency injection with Hilt in your app. But, I’d still recommend enabling HTTPS on MockWebServer to do real-world HTTPS testing.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.