Monday, April 02, 2012

Android Unit Testing - A slightly painful experience

After a few months of mucking around with Android it came to build something substantial. Things have been going fairly well until I started trying to add Unit Tests.

Android provides a complete framework for unit testing which builds on JUnit 3. All in all, this seems pretty good and things are fairly straight forward. The thing that caused the pain and frustration was in resource management.

First of all, let's summarise the test I was trying to implement:

  • My app executes REST requests against a web service. This returns JSON that is then parsed by a Proxy class into my model classes.
  • The REST queries themselves are executed by the Proxy via a RestUtil class.
  • To facilitate testing of the parsing code, the RestUtil class is defined by the interface IRestUtil. The Proxy constructor accepts an IRestUtil object.
  • This allows me to create a MockRestUtil that implements IRestUtil. This can be passed to the Proxy in my unit tests to allow testing of specific responses.


So with that in place I came to implement MockRestUtil. The aim was to get the MockRestUtil to load saved chunks of JSON stored locally as assets. This way I can test a whole variety of responses from the web service easily.

Once it came time to load the resources though, I never got anything back but null. I had been trying to use ClassLoader.getResourceAsStream(), however this returned nothing but null. I also tried making a static application context and using getContext.getAssets(), again nothing but null. I tried a lot of things, however, it wasn't until I hit upon the following Stack Overflow article that I finally got things working: http://stackoverflow.com/questions/9898634/how-to-provide-data-files-for-android-unit-tests

To summarise (based on Eclipse):

1) Right Click on your Test Project and select Build Path -> Configure Build Path
2) Under the Source tab click "Add Folder" and select the Assets directory. Note: Since Version 15 of the ADT plugin, the Assets folder is NOT include in the build path by default. You have to add it manually.
3) Create your data files and add them into the /Assets directory of your test project.
4) To access them in the test case use the following:

String assetPath = "assets/data.json";
InputStream stream = this.getClass().getClassLoader().getResourceAsStream(assetPath);

And there you go. Now you have an easy way to store local data for use in Unit Tests.