目前我为它编写了一个Provider和TestCase。它到目前为止进展顺利,现在我尝试测试通知是否按预期工作。基本上我创建一个ContentObserver并在我的Observer上进行插入。所有插入工作正常,我只是在努力解决通知问题。为此,我在ProviderTestCase中使用CountDownlatch,当调用任何#onChange方法时,它会倒计时:
@SmallTest
public void testUriNotification() throws Exception
{
final TestContentObserver observer = new TestContentObserver(new Handler(), 1);
resolver.registerContentObserver(FavoritesContract.Favorites.CONTENT_URI,true,observer);
final ContentValues values = FavoritesContract.createFavorite(1);
final Uri uri = resolver.insert(FavoritesContract.Favorites.CONTENT_URI, values);
assertNotNull(uri);
observer.latch.await(5, TimeUnit.SECONDS);
assertThat(observer.latch.getCount(), Matchers.is(0L));
resolver.unregisterContentObserver(observer);
}
public static class TestContentObserver extends ContentObserver
{
private CountDownLatch latch;
public TestContentObserver(final Handler handler, final int countDown)
{
super(handler);
latch = new CountDownLatch(countDown);
}
@Override
public boolean deliverSelfNotifications()
{
return true;
}
@Override
public void onChange(final boolean selfChange)
{
latch.countDown();
super.onChange(selfChange);
}
@Override
public void onChange(final boolean selfChange, final Uri uri)
{
latch.countDown();
super.onChange(selfChange, uri);
}
插入方法如下:
@Override
public Uri insert(final Uri uri, final ContentValues values)
{
if (!insertAllowed(uri))
{
throw new IllegalArgumentException("Unsupported URI:" + uri);
}
final SQLiteDatabase db = database.getWritableDatabase();
if (isFavoriteItem(uri))
{
final long id = db.insert("favorites", null, values);
return getUriForId(id, uri);
}
else if (isFavoriteList(uri))
{
final long id = db.insert("favorites", null, values);
return getUriForId(id, uri);
}
throw new IllegalArgumentException("No matching URI found for:" + uri);
}
private Uri getUriForId(long id, Uri uri)
{
Log.d(LOG_TAG,"getUriForId:"+id+" uri:"+uri);
if (id > 0)
{
final Uri itemUri = ContentUris.withAppendedId(uri, id);
if (!isInBatchMode())
{
// notify all listeners of changes and return itemUri:
Log.d(LOG_TAG, "Notify ContentResolver using :" + uri.toString());
getContext().
getContentResolver().
notifyChange(itemUri, null);
}
else
{
Log.d(LOG_TAG, "Cant notify ContentResolver, we are in Batch Mode for :" + uri.toString());
}
return itemUri;
}
return null;
}
private final boolean insertAllowed(final Uri uri)
{
if (uri == null)
{
return false;
}
return ALLOWED_TYPES.contains(URI_MATCHER.match(uri));
}
private final boolean isFavoriteList(final Uri uri)
{
if (uri == null)
{
return false;
}
return URI_MATCHER.match(uri) == FAVORITE_LIST;
}
private final boolean isFavoriteItem(final Uri uri)
{
if (uri == null)
{
return false;
}
return URI_MATCHER.match(uri) == FAVORITE_ID;
}
所以,CountDownlatch永远不会倒计时。我看到在getUriForId方法中,URI看起来很好。 URI结束插入的/ ID。
我不确定我是否在那里创建了某种死锁,因为Latch等待并且提供者无法使用notifyChange方法调用Observer方法。因此,在5秒后测试失败,因为超时发生了。
答案 0 :(得分:0)
发生的事情是您创建的处理程序绑定到测试线程,因此您永远不会收到回调。您需要使用Looper.getMainLooper来获取对主(线程)处理程序的引用:
new Handler(Looper.getMainLooper());
其他建议,在resolver.insert()之前调用observer.latch.await(),以避免在调用await()之前发生回调时的片状测试。
使用@MediumTest或@LargeTest注释此测试。您应该只使用@SmallTest进行单元测试。
使用assertTrue(observer.latch.getCount()< = 0),在这种情况下更易读,或者你想坚持使用hamcrest Matchers,assertThat(observer.latch.getCount(),equalTo(0L));