Testing REST APIs Using MockWebServer
Learn how to mock a REST API with MockWebServer and easily test your business logic using Espresso to check how your UI handle success or error responses. By Subhrajyoti Sen.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Testing REST APIs Using MockWebServer
20 mins
- Getting Started
- Why Use a Mock Server to Test API Calls?
- Why Use MockWebServer Over Manual Client Mocking?
- Configuring MockWebServer
- Changing the API URL
- Creating a Test Runner
- Using Espresso
- Setting up MockWebServer
- Setting up a Mock Response
- Creating a JSON Response
- Creating a File Reader to Read the Response
- Writing the Tests
- Setting up an Idling Resource
- Testing a Successful Case
- Testing a Failed Response
- Where to Go From Here?
MockWebServer is a library from Square, the people who made Retrofit and OkHttp. MockWebServer allows you to easily test how your apps behave when making HTTP/HTTPS calls.
A mock web server is a program that simulates the behavior of an actual remote server but doesn’t make calls over the internet. This makes it easy to test scenarios without internet access and without having to alter your remote server.
In this tutorial, you’ll learn:
- The benefits of using a mock server while testing.
- How to set up MockWebServer.
- How to make MockWebServer mock the behavior of your actual server.
- How to write UI tests to make sure your app functions as expected.
You’ll do this by working on a What’s The Meme app, which displays a list of popular meme templates and their names.
Getting Started
Download the starter project by using the Download Materials button at the top or bottom of the tutorial.
You’ll find a starter project and a final project inside the materials.
Some of the files in the starter project are:
- MemeAdapter.kt: A RecyclerView adapter that displays the list of memes.
- MemeModel.kt: A Kotlin data model that represents each meme.
- MainActivity.kt: Displays the list and the error states, when required.
-
MainViewModel.kt: Interacts with
MemeRepository
and emits state toMainActivity
. - OkHttpProvider.kt: Contains a helper method to access a networking client.
- MemeApi.kt: Contains a method corresponding to the API call you want to make.
In this tutorial, you’ll focus less on the code from the files above and more on setting up MockWebServer and writing tests.
Open Android Studio and select Open an existing Android Studio project. Select starter from the materials folder.
After you’ve imported the starter project, build and run. You’ll see a screen like this:
Why Use a Mock Server to Test API Calls?
Before setting up your MockWebServer, you might wonder why you’d want to test your API calls.
Doing this provides a few advantages:
Sometimes, the API might give responses that aren’t straightforward to serialize and deserialize directly. In other cases, you might want to convert the data from your API response from one data type to another. For example, the API might return dates as String
s, but you want to use them as DateTime
objects.
For such cases, you might write an adapter to convert the data. A mock web server makes it easy to test whether these adapters are working as expected when making API calls.
It can be tricky to test whether apps handle empty and error states properly when dealing with a remote server. Servers are designed to be as reliable as possible, making it challenging to get error responses while testing. Using a mock server lets you easily emulate error responses and see if the app handles them correctly without changing your actual server.
- Testing Adapters Is Easy
- Testing Empty and Error States
Sometimes, the API might give responses that aren’t straightforward to serialize and deserialize directly. In other cases, you might want to convert the data from your API response from one data type to another. For example, the API might return dates as String
s, but you want to use them as DateTime
objects.
For such cases, you might write an adapter to convert the data. A mock web server makes it easy to test whether these adapters are working as expected when making API calls.
It can be tricky to test whether apps handle empty and error states properly when dealing with a remote server. Servers are designed to be as reliable as possible, making it challenging to get error responses while testing. Using a mock server lets you easily emulate error responses and see if the app handles them correctly without changing your actual server.
Why Use MockWebServer Over Manual Client Mocking?
Now that you’re sold on testing your API calls, you might wonder why you should use MockWebServer when you could just mock out whatever class makes your API calls. Here are a few reasons:
- MockWebServer exercises the full HTTP stack, which would be tedious to do manually.
- You don’t need to make changes on the app side when using a MockWebServer.
- It’s easy to recreate edge-cases such as throttling and rare error codes.
Configuring MockWebServer
In this section, you’ll save a response to a JSON file and configure a MockWebServer instance to return the saved response.
Changing the API URL
The base URL for the app is stored in MemeApp
. Open MemeApp.kt
and look for the following function:
open fun getBaseUrl() = "https://api.imgflip.com"
When you create a test with a mock server, the app shouldn’t use the real URL. Instead, it should use the mock server’s URL. To set this up, you’ll need a mechanism to tell the app to use the real URL usually but the mock URL when you run tests.
A test runner makes this possible. It helps you configure the conditions you use to run your tests.
First, you must create an equivalent of MemeApp
that returns the mock URL instead of the real URL.
Do this by creating a file in the androidTest folder and naming it MemeTestApp.kt. Add the following code to it:
package com.company.android.whatsthememe
class MemeTestApp : MemeApp() {
var url = "http://127.0.0.1:8080"
override fun getBaseUrl(): String {
return url
}
}
Here, http://127.0.0.1
is the local URL of your computer and 8080
is the port MockWebServer will use.
After you add the MemeTestApp.kt file, your package structure should look like this:
Creating a Test Runner
Now, you need to provide a test runner that uses MemeTestApp
instead of MemeApp
when running a test.
Create a file in the androidTest folder and name it MockTestRunner.kt. Add the following code to it:
package com.company.android.whatsthememe
import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
class MockTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?,
context: Context?): Application {
return super.newApplication(cl, MemeTestApp::class.java.name, context)
}
}
newApplication()
provides the application instance you’ll use in the test. You can see it returns an application instance using MemeTestApp
instead of MemeApp
.
Now that you’ve written a test runner, you need to tell Gradle to use it for your project. To do this, open the app-level build.gradle and change the value of testInstrumentationRunner
as follows:
testInstrumentationRunner "com.company.android.whatsthememe.MockTestRunner"
Click Sync Now and let Gradle finish syncing. From now on, Gradle will use MockTestRunner
whenever you run any UI tests.
To use a mock web server and verify that it’s working as expected, you’ll write a few Espresso tests next.