Running plain JUnit tests with Resource files in Android Studio

I’m currently writing a podcast app for Android in my spare time. I haven’t yet read any books or done any courses on it yet, though I’ve signed up for a Coursera course called ‘Programming Mobile Applications for Android Handheld Devices’ in the hope of learning some theory behind what I’m thrashing out. So I’m not quite sure what the standard practices are for unit testing. The way an Android project is set up by default is that the tests have to run on a device or an emulator (and I’ve never got the emulator to work.) This feels strange to me – the .NET orthodoxy is that you should be able to test logic independently of the platform it runs on. So I’ve split up my Android project into my main ‘App’ module, which contains all the things which depend on hardware, such as UI, network and storage, and some pure Java modules containing the business logic, such as how to retrieve objects from the SQLite database and how to parse podcast XML into Java objects.

podcastAppStructure

Yesterday I was writing testing my XML parsing logic, so I put a test XML file inside my test assembly as a resource:

TestPodcastXml

And I tried to load that resource in my test:

    @Test
    public void canReadSerial() throws IOException, XmlPullParserException {
        
        InputStream xmlInputStream = getClass().getClassLoader().
              getResourceAsStream("serialPodcastXml.xml");

But when I ran the test, I kept on getting a NullPointer inspection. The file was definitely in the jar – I checked by finding the jar in the filesystem and ran jar tf to list its contents.

The problem turned out to be that when Android Studio runs the tests, it runs the classes from the .class files rather than from the jar, and so therefore it couldn’t find the resource file. So after a bit of trial and error, I came across this solution:

  • Go to the .iml file of your test package
  • Find this section:
<component name="NewModuleRootManager" inherit-compiler-output="false">
    <output url="file://$MODULE_DIR$/build/classes/main" />
    <output-test url="file://$MODULE_DIR$/build/classes/test" />
  •  Replace the url attribute of the <output> element:
<component name="NewModuleRootManager" inherit-compiler-output="false">
    <output url="file://$MODULE_DIR$/build/libs/<YOUR MODULE NAME>.jar" />
    <output-test url="file://$MODULE_DIR$/build/classes/test" />

This means that the tests will run from the jar rather than the class files, and you’ll be able to access your resource files. I don’t know if this has any unwanted side-effects, but it’s working for me so far.