Testing in Flutter | Mocking network calls

Akshat kaneria
Flutter Clan
Published in
4 min readFeb 27, 2021
Photo by Markus Spiske on Unsplash

Introduction:

In this post, we’ll be discussing about how to mock network calls while writing widget or unit tests for your Flutter app. We’ll be using Dio, which is one of the most popular package, for handling network calls as it provides functionalities such as cancelling network requests, locking and unlocking network requests, adding interceptors, etc.

For mocking network calls we’ll be using Mockito which provides a lot of functionalities for mocking dependencies while testing.

Getting Started:

First of all, I have created a simple Flutter app which contains two buttons on the home screen and both the buttons will initiate different API requests when pressed. The data received from the API call is then displayed in the boxes above the buttons.

The working of the app is shown below:

I have created a class named ApiService which contains a method to get a Dio object and other methods to make network calls using that Dio object.

The implementation is as below:

Let’s analyze the getDioClient() in the above ApiService class:

For detecting whether the app is running in test environment i.e. during unit/widget tests or not, we check if the FLUTTER_TEST key is present in Platform.environment.

Platform.environment.containsKey('FLUTTER_TEST')

All the Dio objects have a HttpClientAdapter which is a bridge between Dio and HttpClient. HttpClient is the real object that makes Http requests. In the code above, if the app is running in the test environment, we set the HttpClientAdapter of Dio to an object of DioAdapterMock for the purpose of avoiding real time API requests and instead mocking the API requests to return the desired response while testing as shown below.

dio.httpClientAdapter = DioAdapterMock();

DioAdapterMock is a class which is an extension of class Mock, which is provided by Mockito package and allows us to create mock implementations. It implements the HttpClientAdapter, the functionality of which is already discussed above. DioAdapterMock is a singleton class as the same instance is needed in widget/unit tests and ApiService class. If we mock a response in a particular test using an instance of it, then the same instance is used as HttpClientAdapter of Dio object while making API request.

The code for the class DioAdapterMock is as below:

Time to write some tests.

Writing widget tests:

Scenario: We click on the first button to make an API request and display the response received in the container above the button.

Now, we’ll mock this API request using DioAdapterMock to return the desired response rather than making a real network call:

Here, we use when, which is provided by Mockito, to mock the API call so that it returns the response that we have set i.e. httpResponse.

when(dioAdapterMock.fetch(any, any, any))
.thenAnswer((_) async => httpResponse);

Here’s the result of this test:

Now, consider the case when there are multiple consecutive API requests. In this case, the above implementation will fail as:

  1. It mocks only the immediate next API request and other requests after that won’t be mocked.
  2. Different APIs will have different responses.

Thus, to cater to multiple APIs, we can mock them on the basis of RequestOptions such as path, base URLs, etc.

Below is the implementation of mocking multiple API requests with the help of path parameter of RequestOptions:

In the code above, if the RequestOptions of the API request has path data1, then httpResponse1 will be returned and similarly if the RequestOptions has path data2, then httpResponse2 will be returned. Thus, we were able to mock multiple API requests based on the path in the request options.

Here’s the result of this test:

Thank you for reading this article. If you liked this article, then clap 👏 as much as you can and share it with your friends. You can find the complete source code here:

--

--