Модульные Тесты Android, Требующие Контекста
Я пишу свой первый бэкэнд базы данных Android, и я изо всех сил пытаюсь тестировать создание моей базы данных.
В настоящее время проблема, с которой я сталкиваюсь, - это получение допустимого объекта контекста для передачи моей реализации SQLiteOpenHelper. Есть ли способ получить объект контекста в классе, расширяющем TestCase? Решение, о котором я подумал, заключается в создании экземпляра действия в методе установки моего тестового случая, а затем присвоении контекста этого действия переменной поля что мои методы тестирования могут получить доступ...но, похоже, должен быть более простой способ.
Спасибо за Ваш вклад!
Мэйси
8 ответов:
вы можете попробовать переключиться на AndroidTestCase. Глядя на документы, кажется, что он должен быть в состоянии предоставить вам действительный контекст для передачи в SQLiteOpenHelper.
изменить: Имейте в виду, что вам, вероятно, придется настроить свои тесты в "тестовом проекте Android" в Eclipse, так как тесты будут пытаться выполнить на эмуляторе (или реальном устройстве).
если вы запускаете свои тесты с
AndroidJUnit4
, вы можете использоватьInstrumentationRegistry
методы для получения контекста:
InstrumentationRegistry.getTargetContext()
- обеспечивает применениеContext
целевого приложения.
InstrumentationRegistry.getContext()
обеспечиваетContext
из пакета этого инструментария.
С помощью
AndroidTestCase:getContext()
метод только дает заглушку контекст в моем опыте. Для моих тестов я использую пустую активность в своем основном приложении и получаюContext
через это. Я также расширяю класс набора тестов с помощьюActivityInstrumentationTestCase2
класса. Кажется, работает на меня.public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity> EmptyActivity activity; Context mContext = null; ... @Before public void setUp() { activity = getActivity(); mContext = activity; } ... //tests to follow }
что делают остальные?
можно получить из MockContext и вернуть например a MockResources on
getResources()
, действительного ContentResolver ongetContentResolver()
и т. д. Это позволяет, с некоторой болью, некоторые тесты.альтернативой является запуск например Robolectric который имитирует всю ОС Android. Это было бы для системные тесты: это намного медленнее работать.
расширение AndroidTestCase и вызов AndroidTestCase: getContext () отлично работает для меня, чтобы получить контекст и использовать его с SQLiteDatabase.
единственное неудобство заключается в том, что база данных, которую он создает и/или использует, будет такой же, как и в производственном приложении, поэтому вы, вероятно, захотите использовать другое имя файла для обоих
например.
public static final String NOTES_DB = "notestore.db"; public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db";
сначала создайте тестовый класс под (androidTest).
теперь используйте следующий код:
public class YourDBTest extends InstrumentationTestCase { private DBContracts.DatabaseHelper db; private RenamingDelegatingContext context; @Override public void setUp() throws Exception { super.setUp(); context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_"); db = new DBContracts.DatabaseHelper(context); } @Override public void tearDown() throws Exception { db.close(); super.tearDown(); } @Test public void test1() throws Exception { // here is your context context = context; }}
альтернативное решение состоит в том, чтобы избежать использования
ApplicationTestCase
илиAndroidTestCase
или любой другой класс, который зависит отContext
. Дело в том, что нет необходимости тестироватьSQLite
илиORM
рамки, так что вы можете создать интерфейс с basicCRUD
методы:public interface UsersManager{ User createUser(String userId); User getUser(String userId); boolean updateUser(User user); boolean deleteUser(User user); }
и реализовать две версии: одна для тестов, а другой для производственной среды. Версия для тестов может быть легко реализована с помощью
HashMap
:public class TestUsersManager implements UsersManager{ private HashMap<String, User> users = new HashMap(); public User createUser(String userId){ User result = new User(userId); users.put(userId, user); return result; } //... other methods }
он работает быстро (нет диска
IO
в случаеSQLite
) и не имеет внешних зависимостей. Кстати, это тоже дополнительный уровень абстракции: для производственного кода Вы можете легко переключаться междуORM
фреймворки, например.