Unit Testing Android Resources with Kotlin and ResourceProvider

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

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

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.

Director, Mobile Product Engineering at Realogy