Testing Android In-App Updates with FakeAppUpdateManager

Malvin Sutanto
Wantedly Engineering
4 min readOct 29, 2019
Photo by Charles on Unsplash

“In-app updates” is a new feature from Google Play that enables us to prompt our active users to update to the latest version of our app. It allows our users to update straight from the app instead of from Google Play Store. There are 2 types of user experience that we can choose: Flexible and Immediate.

  • Flexible: An update is downloaded in the background and users will be prompted to install the update once the download is complete.
  • Immediate: Users will be asked to update and restart the app in order to continue using the app.

To implement the in-app update flow in our app, we can follow the official documentation provided by Google: https://developer.android.com/guide/app-bundle/in-app-updates

You can find my implementation of the in-app updates here:

Testing In-App Updates

Let’s assume that we have implemented the in-app updates of our app according to the official documentation. How can we test that the update flow is behaving as we want?

One way to test that the update flow is triggered correctly is by uploading a newer version of our app to the Play Store. From there, we can validate that the update prompt is triggered from within the older version of our app that supports in-app updates, download the update, and ensure that it is installed correctly.

However, this is very time consuming and not scalable as we will need to upload multiple versions of our app to test failure and cancellation cases. We also need to be very careful not to accidentally release a test version of our app.

This is where integration tests can help us. In this post, I will talk about how we can utilize FakeAppUpdateManager to write integration tests for this in-app update process and simulate edge cases that are difficult to reproduce.

FakeAppUpdateManager

FakeAppUpdateManager, as its name suggests, is a fake class with methods that we can invoke to simulate user and network behavior during the in-app update process, like userRejectsUpdate or downloadFails. This class is provided by the Google Play core library to make testing edge cases of in-app updates easier.

Full documentation of FakeAppUpdateManager class can be found here: https://developer.android.com/reference/com/google/android/play/core/appupdate/testing/FakeAppUpdateManager.html

However, if we look at the documentation of the methods in FakeAppUpdateManager, most of them have some preconditions, e.g.:

downloadStarts
void downloadStarts ()
Simulates the download starting.
Works only after userAcceptsUpdate().

As FakeAppUpdateManager tries to simulate the flow of the in-app update process, the order of method invocation is important. To understand this invocation order easier, I’ve prepared the diagram below. Green rectangles represent methods that are available in a regular AppUpdateManager class. While blue rectangles are methods that are available in the FakeAppUpdateManager that we can use to simulate user and network behavior during the update process.

FakeAppUpdateManager flow.

To simulate a successful download, for example, we need to invoke startUpdateFlowForResult, userAcceptUpdate, downloadStart, and finally downloadCompletes.

Integration Testing with FakeAppUpdateManager

Let’s say, we want to create an integration test to simulate a successful flexible update of our app, based on the diagram above, we will then structure our test as follows:

A test that simulates a successful flexible update.

Creating the same simulation for a successful immediate update will look like:

A test that simulates a successful immediate update.

Next, as I mentioned before, FakeAppUpdateManager allows us to test edge cases of the in-app update, so let’s create an integration test to simulate a failure in the download process of the update. It will look like this:

A test that simulates a failed flexible update.

The full implementation of these tests can be found here:

You may need to use a custom Executor when invoking methods of AppUpdateManager for the integration test to be executed synchronously. Refer to my sample implementation to find out how to accomplish this.

Summary

Implementing FakeAppUpdateManager into our integration test should allow us to easily test edge cases of the in-app update process, while also ensuring that no regression will happen in the future.

However, FakeAppUpdateManager itself has some limitations. For example, some events that are supposed to trigger onActivityResult, such as userAcceptsUpdate and userRejectsUpdate, will not trigger onActivityResult properly when they are simulated through FakeUpdateManager. So we might have to structure our code differently or trigger onActivityResult manually with the proper response to account for this difference.

Lastly, even if you have implemented all the integration tests to automate the testing of the in-app update process, do not forget to do a full integration test with Google Play to ensure that everything is working correctly and your users can update to the latest version of your app without any issue.

Thank you for reading my post! I hope you found it interesting and useful. 🎉

--

--