Как протестировать контент-провайдеров на Android
-
06-07-2019 - |
Вопрос
Я пытаюсь протестировать свою базу данных, используя ProviderTestCase2<T>
.Я вижу, как создается тестовая база данных.Таким образом, я полагаю, что тестируемый контент-провайдер должен использовать тестовую базу данных.Но как только я попытаюсь сделать какие-либо звонки против MockContentResolver
(или тот, который создан с newResolverWithContentProviderFromSql
), я получаю UnsupportedOperationException
.Это задокументировано для MockContentResolver как нормальное поведение.Таким образом, я немного не уверен в назначении ProviderTestCase2.
Как вы тестируете своих контент-провайдеров?
Спасибо
Решение
Расширьте ProviderTestCase2, чтобы переопределить getMockContentResolver() и вернуть ваш собственный класс, производный от MockContentResolver.
public class MyProviderTestCase2 extends ProviderTestCase2 {
@Override
public MockContentResolver getMockContentResolver () {
return new MyMockContentResolver();
}
}
MyMockContentResolver должен будет переопределить все методы, которые вы хотите протестировать в вашем ContentProvider .
Тогда вы должны иметь возможность запускать любые тесты, которые вы хотите, на вашем контент-провайдере, пока он изолирован ProviderTestCase2
Другие советы
Насколько я обнаружил, настройка mock content resolver явно не требуется - я мог бы наблюдать случаи, когда это возможно (возможно, правильное разрешение поставщика через URI, настройки, для которых требуется работа corect GetType ()), но для меня этого было достаточно, чтобы сделать что-то вроде этого:
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);
}
}
}
Я добавляю эту запись, поскольку думаю, что она может помочь программистам, которые хотят протестировать своего контент-провайдера.
Представьте, что ваш контент-провайдер называется MyProvider и что у вас есть класс контракта под названием MyProviderContract, определяющий некоторые константы.
Прежде всего, вы напишете тестовый класс под названием MyProviderTestCase
который наследуется от ProviderTestCase2<MyProvider>
.Вам нужно будет определить конструктор, который будет вызывать super
конструктор:
public MyProviderTestCase() {
super(MyProvider.class, MyProviderContract.AUTHORITY);
}
Затем, вместо того, чтобы напрямую обращаться к вашему провайдеру (избегайте использования getProvider()
поскольку пользователи вашего контент-провайдера не получат к нему прямого доступа), используйте getMockContentResolver()
чтобы получить ссылку на средство определения содержимого, а затем вызвать методы этого средства определения содержимого (query
, insert
, и т.д.).В следующем коде я показываю, как протестировать insert
способ.
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);
}
Затем вы можете добавить столько методов тестирования, сколько захотите, используя распознаватель контента вместо вашего контент-провайдера напрямую, как это сделали бы пользователи вашего контент-провайдера.