Mocking in In-App Purchase UI Tests — Mockito, Dagger2 and Espresso

Augustine Kwong
Aug 31, 2018 · 4 min read
Image for post
Image for post

Testing In-App Purchase (IAP) flow is especially difficult — completing the flow produces side effects that are hard to reverse, e.g. upgrading a user or making a purchase, so it makes sense to mock these calls even in a UI test. In this article we will create Espresso UI Instrumented tests for Android that will proceed through the IAP, mocking the responses from Google Billing and our own user database.

The stack

The process

Create directory your/folder/location/src/androidTest. It should be on the same level as src/main.

Within this directory, mirror your src/main/ directory structure.

  1. Create a test DaggerComponent in /androidTest/com/domain/.../dagger, one that will supply our mocked dependencies.
  2. Create a test DaggerApplication, one that will receive our mocked modules.
  3. Create a test runner that uses our test application.
  4. Write tests! Run with the test runner.

Step one — Dagger Component

A quick overview of Dagger2. In order to provide dependencies:

  1. Specify module classes that provide objects of a certain class type. The class is annotated with @Module and methods are annotated with @Provides. The names don’t matter and are just convention. The return type of the method is what’s used in the graph. For tests, it is useful to annotate all @Provides with @Singleton

2. Specify a Component; An adapter between your modules and your injected fields. @Components can be built and injected into different contexts to provide injected fields.

There are 2 new additions we will ignore for the time being, TestApplication and the inject method.

Step Two — Create a test application

Our tests have a different dependency graph than our production application. Create a test application that uses our test dependency graph.

For Dagger to recognize that the annotations in TestComponent needs to be generated into a TestComponent, add to your build.gradle

Step Three — Specify an instrumented test runner

Set this as the Instrumented Test Runner in build.gradle of your app. Make sure you have:

Step Four — The test class

We’re mostly done. Only the classes in our modules that return mocks will be mocked. Within our test class, retrieve the TestAppplication’s component. Having used @Singleton for the dependencies will allow us to retrieve the same instances to mock certain calls.

In our test class, annotate the mocked classes and inject the test application’s singletons. We stub methods accordingly.


Conclusion

Here are some considerations

  • If you are also using Kotlin, you can only mock interfaces. This should be fine since all APIs should have an interface layer regardless
  • If you are having issues with asynchronous code that uses a loosely defined callback flow, consider using Espresso Idling Resources. The official documentation code says to embed idling resource calls in production code. There is no need for that, just use them inside your mocked calls.
  • Use the right tool for the job; this is a very specific use case so thoroughly consider whether methods need to be mocked in a UI test.

In general, use UI tests to ensure that core flows maintain their functionality. They are an integration and regression test. Adding stub methods when testing this flow is a consideration that shouldn’t be taken lightly.

Image for post
Image for post

About the author

Augustine Kwong is a Combined Major in Computer Science and Statistics at the University of British Columbia. He worked on the Core Mobile team, working predominantly on the Android app but branched out to work on backend in Scala.

Hootsuite Engineering

Hootsuite's Engineering Blog

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store