#android #android-contentprovider #robolectric #android-contentresolver
#Android #android-contentprovider #robolectric #android-contentresolver
Вопрос:
У меня есть класс, который запрашивает хранилище мультимедиа для изображений. Например, у меня есть код, который выглядит как someContentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ... )
. Я хочу проверить, что, помимо прочего, мои запросы к MediaStore верны.
Что я сделал до сих пор в своем тесте, так это:
ContentResolver resolver = new Activity().getContentResolver();
ContentValues values = new ContentValues();
values.put( MediaStore.Images.Media.DATA,
"/fake/path/file1.jpg" );
values.put( MediaStore.Images.Media.DATE_ADDED,
fakeTime.getTime() );
resolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values );
Я внедряю этот преобразователь в свой класс, который выполняет запрос к нему. Однако запрос возвращает null. Я видел этот пост:http://ikaruga2.wordpress.com/2013/07/29/roboelectric-and-contentresolverscontentproviders / в котором говорится о регистрации поставщика контента с использованием ShadowContentResolver, так что, что-то вроде:
ShadowContentResolver.registerProvider( MediaStore.AUTHORITY, <SOMETHING_GOES_HERE> );
но я не знаю, что указать для поставщика контента. Может быть, использовать MediaStore
объект? Нет, это не ContentProvider
. Возможно, это MediaProvider
? По какой-то причине символ не может быть разрешен.
На данный момент у меня есть серьезные сомнения в том, что это даже отдаленно правильный подход. Может ли кто-нибудь направить меня в правильном направлении?
используя Robolectric 2.4 snapshot и API 19.
Комментарии:
1. Вы уже нашли решение?
2. @SebastianRoth нет, у меня нет.
Ответ №1:
Вы можете полагаться на ShadowContentResolver.setCursor(Uri, BaseCursor)
и RoboCursor
для создания тестовых данных и проверки запроса. RoboCursor
не обеспечивает полной реализации нескольких методов, поэтому вы можете либо переопределить и проигнорировать их, либо сделать что-то значимое. RoboCursor
расширяет BaseCursor
, переопределяя setQuery()
позволяет перехватывать запросы и проверять или что-то там делать. Используя Robolectric 3.0.
RoboCursor cursor = new RoboCursor() {
@Override
public void registerContentObserver(ContentObserver observer) {
// no op
}
@Override
public void unregisterContentObserver(ContentObserver observer) {
// no op
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
// no op
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// no op
}
@Override
public boolean isClosed() {
return true;
}
};
cursor.setColumnNames(Arrays.asList(MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
cursor.setResults(new Object[][]{
new Object[]{1L, "WhatsApp"},
new Object[]{2L, "Photos"},
new Object[]{3L, "WhatsApp"}
});
shadowOf(ShadowApplication.getInstance().getContentResolver())
.setCursor(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor);
Ответ №2:
У меня была аналогичная проблема с MediaStore, в моем случае класс пытался получить доступ к MediaStore через управляемый запрос. При запуске теста, который проходил по такому кодовому пути, тест завершился неудачно с NPE, поскольку запрос вернул null, как и в вашем случае.
Метод, вызывающий нарушение
public String getPath(Uri uri, Activity activity) {
String[] projection = { MediaColumns.DATA };
Cursor cursor = activity
.managedQuery(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
Учитывая, что вы уже внедряете (я внедряю зависимости с помощью Dagger в свой проект) распознаватель, вы можете либо издеваться над ним, если это вас устраивает (например, через Mockito), либо частично издеваться над ним, поэтому метод-нарушитель по умолчанию использует возвращаемое значение.
PhotoUtilities pu=Mockito.spy(new PhotoUtilities());
Mockito.doReturn(Constants.getDataDir().getAbsolutePath() "/aaa.txt").
when(pu).getPath(Mockito.isA(Uri.class), Mockito.isA(Activity.class));
Таким образом, при попытке запуска теста getPath()
запрос не выполнялся, а использовалось возвращаемое значение по умолчанию, установленное в частичном макете, что позволяло продолжить тест.
Я знаю, что это может быть не совсем то, что вы ищете, но это может удовлетворить ваши потребности, как это было для меня.
Комментарии:
1. Я действительно хочу проверить запрос. Тем не менее, спасибо за ответ!