Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to JUnit test ContentResolver.notifyChange

I'm writing tests for a ContentProvider, in insert I'm notifying about changes with getContext().getContentResolver().notifyChange(mUri, null);

my tests class extends ProviderTestCase2. I created the following mock ContentObserver class:

private class ContentObserverMock extends ContentObserver {
    public boolean changed = false;

    public ContentObserverMock(Handler handler) {
        super(handler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onChange(boolean selfChange) {
        changed = true;
    }

    @Override
    public boolean deliverSelfNotifications() {
        return true;
    }
}

and this is the test case:

public void testInsertNotifyContentChanges() {
    ContentResolver resolver = mContext.getContentResolver();
    ContentObserverMock co = new ContentObserverMock(null);

    resolver.registerContentObserver(CONTENT_URI, true, co);

    ContentValues values = new ContentValues();
    values.put(COLUMN_TAG_ID, 1);
    values.put(COLUMN_TAG_CONTENT, "TEST");

    resolver.insert(CONTENT_URI, values);
    assertTrue(co.changed);
}

seems like onChange is never called, I also tried ContentObserverMock co = new ContentObserverMock(new Handler()); with the same result.

what am I doing wrong here ?

like image 933
Gal Ben-Haim Avatar asked Jul 14 '12 08:07

Gal Ben-Haim


2 Answers

ProviderTestCase2 uses MockContentResolver. Checking source code, it's notifyChange method does nothing.

@Override
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
}

Your scenerio can't be tested with ProviderTestCase2. Take a look at ProviderTestCase3, but it uses android private packages.

Edit: I have made a library consisting of new ProviderTestCase3 class as a replacement for ProviderTestCase2 that keeps calls to ContentResolver.notifyChanged internal to observers registered with ProviderTestCase3.registerContentObserver. You can use it to test notify changes. https://github.com/biegleux/TestsUtils

Usage:

public void testInsertNotifyContentChanges() {
    ContentObserverMock observer = new ContentObserverMock(new Handler()); 
    registerContentObserver(CONTENT_URI, true, observer);
    ContentValues values = new ContentValues();
    values.put(COLUMN_TAG_ID, 1);
    values.put(COLUMN_TAG_CONTENT, "TEST");
    getMockContentResolver().insert(CONTENT_URI, values);
    assertTrue(observer.mChanged);
}

Don't forget to extends ProviderTestCase3<YourProvider>.

like image 186
biegleux Avatar answered Oct 14 '22 03:10

biegleux


I use Robolectric to unittest as much as I can without running the emulator. I verified calling an update on the contentResolver like this:

ShadowContentResolver contentResolver = Robolectric.shadowOf(
    service.getContentResolver());
final List<NotifiedUri> notifiedUris = contentResolver.getNotifiedUris();
assertThat(notifiedUris.get(0).uri, is(uriToVerify));
like image 20
koljaTM Avatar answered Oct 14 '22 03:10

koljaTM