Question

I am trying to test my DB using ProviderTestCase2<T>. I can see the test DB being created. As such I suppose, the tested content provider should use the test DB. But as soon as I try any calls against the MockContentResolver (or the one created with newResolverWithContentProviderFromSql), I get an UnsupportedOperationException. This is documented for the MockContentResolver as normal behavior. As such I am a bit unsure on the purpose of the ProviderTestCase2.

How do you test your content providers?

Thanks

Was it helpful?

Solution

Extend ProviderTestCase2 to override getMockContentResolver() and return your own class derived from MockContentResolver.

public class MyProviderTestCase2 extends ProviderTestCase2 {
    @Override
    public MockContentResolver getMockContentResolver () {
        return new MyMockContentResolver();
    }
}

MyMockContentResolver will need to override any methods you want to test in your ContentProvider.

Then you should be able to run any tests you want on your content provider while it's isolated by ProviderTestCase2

OTHER TIPS

As far as I found, setting up the mock content resolver is not explicitly necessary - I might oversee cases where it is(maybe correct resolving of the provider via URI, hings that need corect getType() working), but for me, it was enough to do something like this:

package org.droidcon.apps.template.provider.test;

import org.droidcon.apps.template.provider.ProfileContract;
import org.droidcon.apps.template.provider.ProfileProvider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.ProviderTestCase2;

public class ProfileProviderTest extends ProviderTestCase2<ProfileProvider> {

    public ProfileProviderTest() {
        super(ProfileProvider.class, ProfileProvider.class.getName());
    }

    protected void setUp() throws Exception {
        super.setUp();
    }


    /**
     * Very basic query test.
     * 
     * Prerequisites: 
     * <ul>
     * <li>A provider set up by the test framework
     * </ul>
     * 
     * Expectations: 
     * <ul>
     * <li> a simple query without any parameters, before any inserts returns a 
     * non-null cursor
     * <li> a wrong uri results in {@link IllegalArgumentException}
     * </ul>
     */
    public void testQuery(){
        ContentProvider provider = getProvider();

        Uri uri = ProfileContract.CONTENT_URI;

        Cursor cursor = provider.query(uri, null, null, null, null);

        assertNotNull(cursor);

        cursor = null;
        try {
            cursor = provider.query(Uri.parse("definitelywrong"), null, null, null, null);
            // we're wrong if we get until here!
            fail();
        } catch (IllegalArgumentException e) {
            assertTrue(true);
        }
    }
}

I add this entry as I think it can help programmers that want to test their Content Provider.

Imagine your Content Provider is called MyProvider and that you have a contract class called MyProviderContract defining some constants.

First of all, you'll write a test class called MyProviderTestCase that inherits from ProviderTestCase2<MyProvider>. You'll have to define a constructor which will call the super constructor:

public MyProviderTestCase() {
    super(MyProvider.class, MyProviderContract.AUTHORITY);
}

Then, instead of using directly your provider (avoid using getProvider() as users of your content provider won't access it directly), use the getMockContentResolver() to obtain a reference to a content resolver and then call the methods of this content resolver (query, insert, etc.). In the following code, I show how to test the insert method.

public void testInsert() {
    Uri uri = MyProviderContract.CONTENT_URI;
    ContentValues values = new ContentValues();
    values.put(MyProviderContract.FIELD1, "value 1");
    values.put(MyProviderContract.FIELD2, "value 2");
    Uri resultingUri = getMockContentResolver().insert(uri, values);
    // Then you can test the correct execution of your insert:
    assertNotNull(resultingUri);
    long id = ContentUris.parseId(resultingUri);
    assertTrue(id > 0);
}

Then you can add as many test methods as you want, using a content resolver instead of your content provider directly, as would do users of your content provider.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top