Tuesday, April 20, 2010
JMock on Android
I am developing a very simple application for Android (more about this in a later post) and wanted to add some Unit Tests: these have always been notoriously difficult to add and use in the Android SDK, but recently the task has been made marginally less cumbersome by the adding a 'parallel' Test project to the one under development in Eclipse.
The process is documented here, so I won't repeat it and I'll assume you have happily created a Test project alongside your Android project.
An excellent intro to testing on Android can also be found in Diego Torres Milano's presentation to DroidCon 2009, and in other entries in his blog.
However, what turned out to be not-so-straightforward was how to add the ability to use jMock as a mocking framework, as I kept getting NoClassDefFoundErrors when launching the unit tests on the Mockery class and others, despite having added them to the classpath.
It turns out that if you add the three required jars for jMock (jmock-2.5.1.jar, hamcrest-core-1.1.jar and hamcrest-library-1.1.jar) as a "User Library" in the Project's build path (the sensible thing to do, in Eclipse) they will not be added to the classpath: neither in the Project nor the Test Project (even if you mark that User Library to be 'exported' as suggested here).
The only way to make it all work, is to add the individual JARs to the Test Project's build path, all three of them.
However (and here's the twist) given that both hamcrest-core and hamcrest-library have a LICENCE.txt file (and a MANIFEST) the APK builder will complain about duplicate files and refuse to import one (or both) of the JARs: the only solution (as suggested here) is to unpack the JARs into a single directory (one of both the LICENCE and MANIFEST files will be overwritten -- not sure whether this will cause a breach of the licensing terms?) and then re-pack them into a single hamcrest-all-1.1.jar file, and include that one into the build path.
Given that I wasted a couple of hours trying to figure out what was preventing Android to accept jMock, I thought I'd post this quick one to help out others.