8

I am using InstrumentationTestCase to unit test a component of my application.

The component persists data to the internal storage and uses Context::fileList(); to retrieve the persisted files.

I experience the following problem: Using this method in the app (on the device) works perfectly fine. But when I try to (Android-)Unit-Test (also on the Device) with use of InstrumentationTestCase I get a NullPointerException inside the fileList() method. I digged into the android source and found out that getFilesDir() (see source here) returns null and causes this error.

The code to reproduce is the following:

public class MyTestCase extends InstrumentationTestCase
{   
    public void testExample() throws Exception
    {
        assertNotNull(getInstrumentation().getContext().getFilesDir()); // Fails
    }
}

My questions are: Is this behaviour intended? What can I do to circumvent this issue? Am I using InstrumentationTestCase right or should I use something different?

I found this question but I'm not sure if this covers the same problem I have.

Community
  • 1
  • 1
Briareos386
  • 1,927
  • 18
  • 34
  • 1
    Did you try to use getTargetContext() instead of getContext() – Blackbelt Jan 14 '13 at 13:13
  • Well, yes. `getTargetContext()` works as expected, but I want the tests to run (more or less) independently of the App. That's the reason I chose `InstrumentationTestCase`. – Briareos386 Jan 14 '13 at 13:32
  • As the name stated, InstrumentationTestCase is an instrumentation test, by using the second test app to instrument the main app for testing Android component, for instance activity is properly renderred or user interaction is correctly handled. It doesn't make much sense to run the test app independently from the main app. – yorkw Jan 17 '13 at 20:14
  • @yorkw Yeah, I already was in doubt if this is correct what I am doing. So in case I need a prepared dataset, would you suggest the following? Perform a 'backup' of current data, write the prepared dataset, perform test, delete test data, restore backup? – Briareos386 Jan 22 '13 at 08:00

2 Answers2

10

I think that you are right with keeping your test data separate from tested application.

You can fix problem with Null by creating files directory for Instrumentation app by executing the following commands

adb shell
cd /data/data/<package_id_of_instrumentation_app>
mkdir files

You can do above only on emulator or rooted device.

Then test from your question will not fail. I did it and also uploaded file named tst.txt to files dir, all below tests were successful:

assertNotNull(getInstrumentation().getContext().getFilesDir());
assertNotNull(getInstrumentation().getContext().openFileInput("tst.txt"));
assertNotNull(getInstrumentation().getContext().openFileOutput("out.txt", Context.MODE_PRIVATE));

But I think more convenient way to provide data to test project is to use assets of test project where you can simply save some files and open them:

assertNotNull(getInstrumentation().getContext().getAssets().open("asset.txt"));

or if you want to save some results of tests to the file you can use ExternalStorage:

File extStorage = Environment.getExternalStorageDirectory();
assertNotNull(extStorage);
Michal
  • 2,074
  • 2
  • 22
  • 29
1

@Blackbelt mentioned in his comment to use getTargetContext() instead of getContext(). I missed the comment, and after a few hours, of trying to figure out how to Realm.init() from an Android instrumented tests, I find out that I need the Context from getTargetContext()...(along the way, i tried to context.filesDir.mkdirs())

package com.github.ericytsang

import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Test

class InstrumentedTest {

    private val context = InstrumentationRegistry.getInstrumentation().targetContext

    @Test
    fun can_mkdirs() {
        assert(context.filesDir.mkdirs())
    }
}
Eric
  • 16,397
  • 8
  • 68
  • 76