Модульные Тесты Android, Требующие Контекста


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

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

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

Мэйси

8 52

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
}

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

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

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

альтернативой является запуск например 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 рамки, так что вы можете создать интерфейс с basic 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 фреймворки, например.