NullPointerException в учебном руководстве по тестированию активности - PullRequest
3 голосов
/ 15 июня 2010

В настоящее время я пробую учебное пособие по тестированию активности ( Найдено здесь ), и у меня возникла проблема. Кажется, что всякий раз, когда я пытаюсь вызвать что-то внутри UIThread, я получаю исключение java.lang.NullPointerException.

public void testSpinnerUI() {
    mActivity.runOnUiThread( new Runnable() {  
        public void run() {  
            mSpinner.requestFocus();
        }  
    });  
}

Это дает мне:

Не завершено: java.lang.NullPointerException

и ничего больше. Я попробовал это на двух разных образцах сейчас, с тем же результатом. Я попытался с помощью предложения try / catch для вызова mSpinner.requestFocus (), и кажется, что mSpinner имеет значение null внутри потока. Я правильно настроил его с помощью функции setUp (), найденной в том же примере, и быстрый assertNotNull (mSpinner) показывает, что mSpinner фактически не равен нулю после функции setUp (). Что может быть причиной этого?

EDIT; хорошо, еще тестирование было сделано. Кажется, что тестируемое приложение сбрасывается между каждым тестом. По сути, это заставляет меня заново устанавливать все переменные между каждым тестом. Это нормально?

Ответы [ 6 ]

6 голосов
/ 16 июня 2010

Хорошо, похоже, теперь у меня все работает. По крайней мере, до определенного момента. Я все еще не могу запустить что-либо внутри runOnUiThread (), но обнаружил, что использование аннотации @UiThreadTest дало мне удовлетворительные результаты. Я больше не получаю NullPointerExceptions, и метод setUp () даже работает правильно. Я понятия не имею, что это было причиной, но, по крайней мере, это работает :)

3 голосов
/ 30 декабря 2011

У меня была такая же проблема. Тесты, которые использовали runOnUiThread () периодически терпели неудачу с NPE на полях-членах моего класса тестирования. В отладчике я мог видеть, что они были нулевыми к тому времени, когда поток пользовательского интерфейса выполнил код.

Насколько я могу судить, runOnUiThread просто отправляет событие, которое позже будет отправлено. К сожалению, это часто происходило после завершения остальной части теста в главном потоке, и мой объект был уничтожен. Это может быть связано с тем, что эмулятор слишком занят, чтобы обработать UIEvent перед продолжением теста.

Мне удалось исправить эту проблему с помощью CyclicBarrier, чтобы убедиться, что мой тест не продолжался до тех пор, пока код не был запущен в UiThread. Я создал метод для инкапсуляции этого и использовал его вместо Activity.runOnUiThread () в моих тестах:

  private void myRunOnUiThread( final Runnable r) {
    final CyclicBarrier barrier = new CyclicBarrier(2);
    mActivity.runOnUiThread(
      new Runnable() {
        public void run() {
          r.run();
          try { barrier.await(); } catch (Exception e) { e.printStackTrace(); }
    }});
    try { barrier.await(); } catch (Exception e) { e.printStackTrace(); }
  }

Вот как это выглядит в моем тестовом классе:

public void testFieldUI() {
        myRunOnUiThread(
                new Runnable() {
                    public void run() {
                        mRateView.requestFocus();
                        mRateView.selectAll();
                    } 
                } 
        ); 
        sendKeys(KeyEvent.KEYCODE_DEL); // delete everything
        assertTrue("rate is deleted", mRateView.getText().length() == 0);
1 голос
/ 31 января 2012

У меня была та же проблема, и, как предположил Дрю, проблема заключалась в том, что класс Test завершил работу и уничтожил мои переменные-члены до завершения UI-потока. Это вызвало исключения нулевого указателя в UI-потоке.

Мое исправление состояло в том, что я создал переменную boolean running, которая сообщает, работает ли UI-поток. Если UI-поток все еще работает, когда основной поток завершает работу, я проверяю, является ли переменная running истинной. Если это так, я сплю, например, 200 миллисекунд, прежде чем пытаться снова. И в UI-потоке последнее, что я установил для runnable значение false, и основной поток также существует.

public void testSomething() {
    activity.runOnUiThread(
            new Runnable() {
                public void run() {
                    // Run something on UI-thread

                    // In the end of this thread, set stillRunning false
                    stillRunning = false;
                }
            });

    while(stillRunning) { 
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // Handle exception
        } 
    }
}
1 голос
/ 29 января 2011

У меня была такая же проблема, как и несколько других странных исключений нулевого указателя. Странно, но это как-то связано с наличием статических переменных-членов в классе тестирования.

Как только я удалил статические ключевые слова из переменных, все проблемы были решены. Это не имеет никакого смысла, поскольку переменные не имеют ничего общего со строкой кода, которая изначально вызывала исключение.

Но теперь все работает ...

1 голос
/ 04 ноября 2010

Не спрашивайте меня, почему, но если вы добавите хотя бы один sendKey () в ваш код, это сработает:

public void testSoundSpinnerUI() {
    myActivity.runOnUiThread(new Runnable() {
        public void run() {
            mySoundSpinner.requestFocus();
            mySoundSpinner.setSelection(0);
        }
    });

    sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
    sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
}
0 голосов
/ 30 июня 2011

Это исключение в основном вызвано другим исключением, которое выдается при запуске вашей деятельности.Из-за этого действие не создается, и вы получаете исключение NullPointException.Попробуйте отладить свои тесты, установив точку останова на место, где вы впервые вызываете getActivity () и обнаруживает ошибку в своем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...