Рубрики
Без рубрики

Тестирование в Android. Тестирование Живых Данных

Введение Теперь, когда я официально выпустил свое первое приложение, которое можно найти ЗДЕСЬ… С тегами java, android, тестирование, тристан.

Вступление

  • Теперь, когда я официально выпустил свое первое приложение, которое можно найти ЗДЕСЬ в магазине Google Play. Я хочу добавить больше функций в свое приложение, однако я думаю, что следующим лучшим шагом будет добавление некоторых тестов. Итак, эта серия будет практической серией, посвященной пониманию тестирования в рамках Android.

Исходный код

  • Вы можете найти мой исходный код здесь

Видео

  • Вы можете найти видеоверсию ЗДЕСЬ

Живые данные

  • Итак, что такое Живые данные? Ну, как изящно сказано в документации, Живые данные - это наблюдаемый класс носителей данных. В отличие от обычного наблюдаемого, LiveData - это программное обеспечение жизненного цикла, то есть оно учитывает жизненный цикл других компонентов приложения, таких как действия, фрагменты или службы. Эта осведомленность гарантирует, что текущие данные обновляют только наблюдателей компонентов приложения, которые находятся в активном состоянии жизненного цикла. Еще не запутался? Добро пожаловать в клуб! В принципе, для целей этого урока мы можем определить текущие данные как необычный класс, реализующий шаблон наблюдателя. Вы можете узнать больше о причудливых деталях живых данных ЗДЕСЬ .

Тестирование Живых Данных

  • Прежде чем мы приступим к тестированию, есть несколько вещей, о которых мы должны знать. Закулисная комната и живые данные реализуют много кода без нашего ведома. Во-первых, все текущие запросы данных к базе данных Room являются асинхронными и выполняются в фоновом потоке. Что дает нам нашу первую проблему, как нам написать код, который заблокирует асинхронный запрос, чтобы мы могли его протестировать? . Ответ на эту проблему состоит из двух частей:

1) наблюдать вечно/наблюдатель 2)Обратный отсчет

наблюдать вечно/наблюдатель

  • В документации Android указано, что Библиотека сохраняемости комнаты поддерживает наблюдаемые запросы, которые возвращают объекты живых данных . Это означает, что мы можем наблюдать за этими запросами и запускать их код, когда они возвращают значение. Это наблюдение выполняется с помощью метода наблюдать вечно() . Этот метод использует класс, реализующий интерфейс Observer , и активирует метод OnChanged() при возврате запроса LiveData. Мы можем сделать это так:
//LiveData query
LiveData> calfLiveDataList = getCalfDao().getAllCalves();

Observer> observer = new Observer>() {
            @Override
            public void onChanged(List listLiveData) {
              //code to run when query returns
            }
        };

calfLiveDataList.observeForever(observer);
  • У этого кода все еще есть одна серьезная проблема, и эта проблема заключается в том, что он не блокируется. Это означает, что мы все еще не можем проводить какие-либо тесты. Чтобы устранить эту проблему, мы реализуем Обратный отсчет .

Обратный отсчет

  • Этот класс является средством синхронизации, которое позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках. Мы инициализируем обратный отсчет с заданным количеством, затем мы можем использовать метод await() для блокировки вашего кода до тех пор, пока не будет вызван метод Countdown() , который освобождает все потоки и разблокирует наш код.
final CountDownLatch latch = new CountDownLatch(1);

Observer> observer = new Observer>() {
            @Override
            public void onChanged(List listLiveData) {
                latch.countDown(); // this releases all the threads

            }
        };

latch.await(2, TimeUnit.SECONDS);
  • Таким образом, наш приведенный выше код будет блокироваться до тех пор, пока не сработает onChange и не будет вызван latch.countdown() . Теперь, когда у нас есть код блокировки, нам просто нужно получить значение из списка живых данных

список Текущих Данных

  • список живых данных представляет данные, возвращаемые запросом живых данных, и он вернет список, содержащий объекты Calf. Это кажется достаточно простым, просто удалите данные, как и любой другой список. Однако оператор new Observer делает этот класс внутренним/вложенным, и при работе с переменными во внутренних/вложенных классах существует несколько специальных правил. Два основных из них, с которыми нам придется компилировать, это:

1) Любая локальная переменная, используемая, но не объявленная во внутреннем классе, должна быть объявлена окончательной

2) Из внутреннего класса вы не можете назначить локальную переменную, но вы можете использовать ссылочный объект.

  • Чтобы соблюдать эти правила, мы создадим конечную переменную ссылочного массива:
final Calf[] data = new Calf[1];
  • Теперь к этой переменной можно обращаться и управлять ею, но внутренними классами, например:
 final CountDownLatch latch = new CountDownLatch(1);

        final Calf[] data = new Calf[1];
        Observer> observer = new Observer>() {
            @Override
            public void onChanged(List listLiveData) {
                latch.countDown(); // this releases all the threads
                data[0] = listLiveData.get(0);
            }
        };
  • данные[0].get(0); это просто присвоение первого значения нашей ссылочной переменной.

Невозможно вызвать наблюдение навсегда в фоновом потоке

  • Теперь мы можем наблюдать за запросом:
calfLiveDataList.observeForever(observer);
  • Однако, если вы попытаетесь запустить этот код, вы получите сообщение об ошибке, в котором будет указано, что Невозможно вызвать наблюдение навсегда в фоновом потоке . Эта ошибка возникает из-за того, что обратный вызов onchange() , который находится в интерфейсе наблюдателя, часто вносит изменения в пользовательский интерфейс. При работе с потоками в Android главное правило: НИКОГДА НЕ ВНОСИТЕ ИЗМЕНЕНИЯ В ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС В ФОНОВОМ ПОТОКЕ . Чтобы обработать эту новую ошибку, нам нужен доступ к основному потоку.

Доступ к основному потоку

  • Чтобы иметь возможность получать доступ к основному потоку и назначать ему задачи, мы будем использовать класс Обработчик .
Handler handler = new Handler(Looper.getMainLooper());
  • Looper.getmainlooper() – это то, что на самом деле дает нам доступ к основному потоку. обработчик предоставляет доступ к очереди задач основного потока, которой мы можем назначить задачу с помощью метода post() .
handler.post(new Runnable() {
                @Override
                public void run() {                    
                       calfLiveDataList.observeForever(observer);
                        }
                    }
       );
  • Запускаемый позволяет нам создать новую задачу для запуска в основном потоке.

Выполнение тестов

  • При правильном внедрении наблюдателя мы теперь можем спокойно проводить тесты:
        Calf returnedCalf = data[0];
        int id = returnedCalf.getId();

        Assert.assertEquals(1,id);
  • В этом тесте я просто проверяю, чтобы убедиться, что объект теленка имеет правильный идентификатор.
  • Спасибо, что нашли время в свой день, чтобы прочитать этот мой пост в блоге. Если у вас есть какие-либо вопросы или проблемы, пожалуйста, прокомментируйте ниже или свяжитесь со мной по Твиттер .

Оригинал: “https://dev.to/theplebdev/testing-in-android-testing-the-room-database-livedata-1cgf”