Home > android, tools > Accessing resources in an AndroidTestCase

Accessing resources in an AndroidTestCase

I am currently writing some tests for low-level (not UI) classes, using AndroidTestCase. These tests need a variety of pre-configured input files, and I though it would be very convenient to provide these as assets packaged with the test application.

Adding the files as assets to the test application was the easy part, while getting access to them from a subclass of AndroidTestCase required a bit of work.

The base class, AndroidTestCase, has a method, getContext(), but it can’t be used to load assets from the test package, because that context refers to the package under test.

Checking the source for AndoridTestCase, I found these two very promising methods:

// AndroidTestCase
    /**
     * Test context can be used to access resources from the test's own package
     * as opposed to the resources from the test target package. Access to the
     * latter is provided by the context set with the {@link #setContext}
     * method.
     *
     * @hide
     */
    public void setTestContext(Context context) {
        mTestContext = context;
    }

    /**
     * @hide
     */
    public Context getTestContext() {
        return mTestContext;
    }

I only needed the getter method, actually, still – it’s marked with “@hide”, which means it can’t be called by applications.

The @hide marker is enforced by not including the method in Android.jar that applications are compiled with. So this method is present on the device, and does what is needed, but is intentionally made inaccessible to applications. I don’t know the reason why, especially considering the comment above the “set” method.

Ok, whatever the reason is… Time to use Java Reflection to access that context.

public class MessageProcessorTest extends AndroidTestCase {

	private final static String TAG = "MessageProcessorTest";

	private Context mContext;
	private AssetManager mAssets;

	@Override
	protected void setUp() throws Exception {
		super.setUp();

		try {
			Method m = AndroidTestCase.class.getMethod("getTestContext", new Class[] {});
			mContext = (Context) m.invoke(this, (Object[]) null);
		} catch (Exception x) {
			Log.e(TAG, "Error getting test context: ", x);
			throw x;
		}

		Log.i(TAG, "Own context: " + String.valueOf(mContext));

		mAssets = mContext.getAssets();
	}

	public final void test_MessageProcessor_1() {

		try {
			String[] list = mAssets.list("dirname");
			for (String s : list) {
				Log.i(TAG, "Source: " + s);
				InputStream stream = mAssets.open("dirname/" + s, AssetManager.ACCESS_STREAMING);
				runOneTest(stream);
				stream.close();
			}

			Log.i(TAG, "End of test");
		} catch (IOException x) {
			Log.e(TAG, "Exception during testing", x);
			fail();
		}
	}

	private static void runOneTest(InputStream stream) {
		// Run a test driven by the data in the stream
	}
}

And here it is. I can now put my data files under assets to supply a variety of data to the test function.

Advertisements
Categories: android, tools
  1. kula85
    July 19, 2013 at 12:56 am

    works really well, thanks

  2. June 24, 2013 at 10:38 pm

    Thank you ! You’ve put an hand on two days of headaches ! 🙂

  3. jlo
    August 11, 2011 at 10:10 pm

    thanks, it’s very useful. You saved me

  1. April 19, 2011 at 2:36 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s