通知URI的ProviderTestCase测试



目前我为它编写了一个Provider和TestCase。到目前为止一切都很顺利,现在我试着测试一下通知是否像预期的那样工作。基本上,我创建了一个contenttobserver,并在我的观察者上执行插入操作。所有的插入都工作得很好,我只是在通知问题上挣扎。为此,我在我的ProviderTestCase中使用CountDownlatch,当任何#onChange方法被调用时,它会得到count down:

@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结束于Insert的/ID。

我不确定我是否在那里创建了某种死锁,因为Latch等待并且提供者不能使用notifyChange方法调用Observer方法。因此,在5秒后,测试失败,因为超时发生了。

实际情况是,您创建的Handler绑定到测试线程,因此您永远不会收到回调。你需要使用loop。getMainLooper获取对主(线程)处理程序的引用:

<>之前 new Handler(Looper.getMainLooper()); 之前

其他建议,在resolver.insert()之前调用observer.latch.await(),以避免在调用await()之前发生回调时出现不稳定的测试。

用@MediumTest或@LargeTest注释这个测试。您应该只在单元测试中使用@SmallTest。

使用assertTrue(observer.latch.getCount() <= 0)在这种情况下更容易读,或者如果你想坚持hamcrest匹配器,assertThat(observer.latch.getCount(), equalTo(0L));

相关内容

  • 没有找到相关文章

最新更新