Flutter: Faking/stubbing backend responses

Pavel Sulimau
Flutter Community
Published in
5 min readDec 10, 2020

Motivation

Sometimes, and it’s not so uncommon, you may need to have a fast, stable, and consistent data source without a need to depend on network calls and real backend service’s data. This is where the approach with faked/stubbed data comes in handy.

So far I’ve needed to fake backends’ data for my apps in the following scenarios:

  • application UI testing;
  • productive client-side development with unstable/non-working/rapidly changing backend.

Goal

Let’s set this reasonable goal for a demo Flutter app: it should be able to fake HTTP(S) responses for the requests it makes, so it can be run and UI tested without a dependency on the real backend.

Implementation

Creating a basic app for the experiments

For the sake of demo I created an app which loads the top headlines from NewsAPI and displays it with a simple ListView widget. Here is how it looks:

App loads headlines from NewsApi (real backend)

Proxying the application’s HTTP(S) traffic

Let’s see the HTTP(S) requests the app makes and the responses it receives from the back-end.
There are several tools which became the de facto standard for proxying web traffic. They are Charles and Fiddler Everywhere.

If you work with native mobile apps you can set an HTTP(S) proxy in your OS (iOS/Android) settings. The OS-wide settings are not honored by Flutter apps (see https://github.com/flutter/flutter/issues/20376), so you may use the following overrides within your app to make it work:

After I applied this configuration to the demo app, I was able to see all the requests and responses coming back and forth:

The core idea of the way to fake data

Since we are able to proxy all the HTTP(S) calls from the app and all the web proxying tools support exporting their sessions in the .har file format, which is basically a json file, we can easily parse the exported ‘.har’ session and use its data as an offline cache.

Using ‘.har’ file as cache source for UI tests

I wrote some UI (integration) tests for this simple app and made sure the app is able to run without dependency on the real backend.

Here are the steps that I made:

1. Exported the Charles session

I exported the Charles session in ‘.har’ format and placed the file inside ‘test_resources’ folder which is in the root of the project. I named this file as ‘top_articles_on_bbc_news’ and also changed its extension to ‘.json’ to make VS Code recognize its content and format it.

2. Embedded the ‘.har.json’ file as an asset in the app

3. Used fake_http_client and http_archive packages to fill the cache with the data from the ‘.har.json’ file

There are a few points that I’d like to draw your attention to in this section. In the following code snippet _ProxySettingHttpOverrides class uses FakeHttpClient and FakeHttpResponse classes from fake_http_client package. It also uses HashMap<HarRequest, HarResponse> _harRequestResponseMap that is constructed from the ‘.har.json’ file data with the help of http_archive package. In the end, _ProxySettingHttpOverrides is set inside main to be used globally.

All of this implies that every HTTP(s) request the app tries to make will get in the FakeHttpClient’s callback. Inside the callback the request will be matched against the requests that are in the hash-map object, and, if the same request was recorded previously, then the corresponding response will be obtained from the hash-map and returned.

4. Wrote some UI tests which run the app that uses the cached data

After the performed changes the app became independent of whether the real backend is working at the time the app is running and whether the backend provides the same data on each call. That means that I could write a UI test which is reliable and repeatable. By the way, here is the introduction to UI (integration) testing in Flutter, that you may found useful.

Here are the simple UI tests that I came up with:

Results

Take a look at how the app was loading during the UI tests run. Please note that the Android emulator was in Airplane mode. That implies that there were no real requests and no real responses from the backend!

App loads headlines from local cache

Conclusions

I hope you’ve got the overall idea of the approach. Feel free to adjust it to your needs and reuse it along with the mentioned packages to make your life easier!

Source code and useful links

--

--