Unit Testing Android Resources with Kotlin and ResourceProvider

Mark Dappollone
3 min readDec 26, 2018

Resources are the blood of any Android application, providing all the built-in constant strings, integers, dimensions, colors and lots of other stuff that’s necessary for conveying ideas to users and laying out screens. But getting those resources is a matter of interacting with the file system, and so logically depends quite heavily on the OS. This dependence on the system to get resources brings with it lots of concerns and difficulties for unit testing functionality that involves resources. You used to be able to mock Resources in unit tests using Android’s MockResources tool, but that’s been deprecated since API 24. You can try to mock the Context and Resources classes themselves, which can get a little tricky, or you can just use instrumentation tests for anything involving Resources, but that’s time consuming and slow.

Lastly, you can create your own testable Resources class, and use that to achieve unit-testable mocks. You could follow this tutorial to do that yourself, or you could use a tool that uses Java Annotation Processing to generate a mockable, Android-agnostic APIs for accessing resources. Enter: ResourceProvider.

How It Works

ResourceProvider generates an API for every Color, Dimension, Drawable, Integer, Id and String (including Plurals) in any of your app’s resources xml files (and your app’s dependency’s resources too!). You can declare a singleton instance of the generated ResourceProvider class and give it an Application Context, and from then on, any object can get resources without needing to know anything at all about Context or Resources or Android.

This functionality is already great for building the most passive MVP views you can imagine and keeping presentation logic in presenters, but the real benefit is that it makes all of that presentation logic unit-testable, including the parts dealing with resources. How?

Since ResourceProvider isn’t tied to the OS at all and isn’t part of the Android SDK, it can be thoroughly mocked and all its functions can be mocked. But ResourceProvider makes it even easier than that. Under the hood, ResourceProvider is actually made up of individual Provider classes for each type of resource:

Since that’s the case, we can create custom Mockito Answer classes to mock each provider’s responses. For the StringProvider, that looks like this:

That Answer class effectively intercepts any call to any StringProvider function, and instead of calling it, returns the name of the function as a String. This preserves the uniqueness of the return value for testing, but eliminated the underlying dependency on Android stuff. And more good news: the new ResourceProvider testutils library includes Answer classes for every resource type in the ResourceProviderAnswers.kt file.

But Wait, There’s More

Of course, since ResourceProvider is generated, that means it doesn’t exist until you build your app. Because of that, the library can’t setup the answers for you. But it can generate the setup for you. That’s right, in the newest version of ResourceProvider, in addition to generating the ResourceProvider class and all its Provider classes, the compiler will also generate a set of Kotlin extension functions for you to use for mocking. So now, if you want to mock string resources in a unit test, you can simply call an extension function to set it up:

Above, in the @Before function we call

resourceProvider.mockStrings()

which is generated by the ResourceProvider testutils compiler. In order to trigger that generation, we just have to include the testutils library in our test dependency block in the build.gradle file:

testCompile 'com.xfinity:resourceprovider:resourceprovider-testutils:1.0.1',

And then seven Kotlin extension functions are generated for us:

If you only need one type of resource, you can just use its individual setup function (i.e. resourceProvider.mockIntegers()), or you can call resourceProvider.mock(), and setup Answers for everything with one call.

Using Android Resources has always been a challenge for both separating concerns and unit testing, but ResourceProvider solves both problems and you don’t have to do any of the work. ResourceProvider will generate both agnostic Resource access APIs and the tools you need to mock and test the functionality you build with those APIs. Using ResourceProvider will enable you to all-but eliminate the need for instrumentation tests to test business logic, and achieve effectively complete unit test coverage for that logic.

And since ResourceProvider is open source, if there are any deficiencies, bugs or missing features, you can always either create an issue, or simply submit a PR and we’ll take a look.

--

--

Mark Dappollone

Director, Mobile Product Engineering at Anywhere Real Estate