Тестирование блоков Android, требующих контекста

Я пишу свой первый бэкэнд на базе Android, и я пытаюсь создать unit test создание моей базы данных.

В настоящее время проблема, с которой я сталкиваюсь, заключается в получении действительного объекта Context для передачи моей реализации SQLiteOpenHelper. Есть ли способ получить объект Context в классе, расширяющем TestCase? Решение, о котором я думал, состоит в том, чтобы создать экземпляр Activity в методе настройки моей TestCase, а затем назначить контекст этого действия переменной поля, к которой могут обращаться мои методы тестирования... но похоже, что должен быть более простой способ.

Спасибо за ваш вклад!

Мэйси

Ответ 1

Вы можете попробовать перейти на AndroidTestCase. От взгляда на документы, похоже, он должен предоставить вам действительный контекст для перехода к SQLiteOpenHelper.

Изменить: Имейте в виду, что вам, вероятно, придется настроить свои тесты в "Android Test Project" в Eclipse, поскольку тесты будут пытаться выполнить на эмуляторе (или на реальном устройстве).

Ответ 2

Вы можете использовать методы InstrumentationRegistry для получения контекста:

InstrumentationRegistry.getTargetContext() - предоставляет Context приложения целевого приложения.

InstrumentationRegistry.getContext() - предоставляет Context этого пакета Инструментов.


Для AndroidX используйте InstrumentationRegistry.getInstrumentation().getTargetContext() или InstrumentationRegistry.getInstrumentation().getContext().

Ответ 3

Использование метода 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
}

Что делают все остальные?

Ответ 4

Вы должны использовать ApplicationTestCase или ServiceTestCase.

Ответ 5

Вы можете получить MockContext и вернуться, например, MockResources на getResources(), действительный ContentResolver на getContentResolver() и т.д. Это позволяет, с некоторой болью, некоторые модульные тесты.

Альтернативой является запуск, например, Robolectric, который имитирует целую ОС Android. Это будет для системных тестов: он намного медленнее запускать.

Ответ 6

Расширение AndroidTestCase и вызов AndroidTestCase: getContext() отлично работает для меня, чтобы получить контекст и использовать его с SQLiteDatabase.

Единственное, что создаёт и/или использует база данных, будет такой же, как та, что используется производственным приложением, поэтому вы, вероятно, захотите использовать другое имя файла для

например.

  public static final String    NOTES_DB      = "notestore.db";
  public  static final String   DEBUG_NOTES_DB = "DEBUG_notestore.db";

Ответ 7

Сначала создайте тестовый класс в (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;
}}

Ответ 8

Ваш тест не является модульным тестом !!!

Когда ты нуждаешься

  • контекст
  • Читать или писать на хранение
  • Сеть доступа
  • Или измените любой конфиг, чтобы проверить вашу функцию

Вы не пишите unit тест.

Вам нужно написать свой тест в пакете androidTest

Ответ 9

Альтернативное решение состоит в том, чтобы избежать использования ApplicationTestCase или AndroidTestCase или любого другого класса, который зависит от Context. Дело в том, что нет необходимости тестировать структуру SQLite или ORM, чтобы вы могли создать интерфейс с помощью базовых методов CRUD:

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.