Bendik
Bendik

Reputation: 928

NullPointerException on Activity Testing Tutorial

I am currently trying the activity testing tutorial (Found here), and have a problem. It seems that whenever I try to call something inside the UIThread, I get a java.lang.NullPointerException.

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

This gives me:

Incomplete: java.lang.NullPointerException

and nothing else. I have tried this on two different samples now, with the same result. I tried with a try/catch clause around the mSpinner.requestFocus() call, and it seems that mSpinner is null inside the thread. I have set it properly up with the setUp() function found in the same sample, and a quick assertNotNull( mSpinner ) shows me that mSpinner is in fact not null after the setUp() function. What can be the cause of this?

EDIT; ok, some more testing has been done. It seems that the application that is being tested resets between each test. This essentially makes me have to reinstantiate all variables between each test. Is this normal?

Upvotes: 3

Views: 2546

Answers (6)

Waltsu
Waltsu

Reputation: 612

I was having the same problem, and as Drew suggested the problem was that Test class finished and destroyed my member variables before UI-thread has finished. That caused Null Pointer Exceptions in UI-thread.

My fix was that I created boolean running variable which tells if UI-thread is still running. If UI-thread is still running, when the 'main'-thread is going to finish, I'm checking if running variable is true. If it is, I'm sleeping for example 200 milliseconds before trying again. And in UI-thread the last thing is that I set runnableto false and main thread exists also.

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
        } 
    }
}

Upvotes: 1

Drew
Drew

Reputation: 31

I was having the same problem. Tests which used runOnUiThread() were failing periodically with NPEs on the member fields of my test class. In the debugger i could see that they were null by the time the UI thread executed the code.

As far as i can tell, runOnUiThread simply posts an event that will later get dispatched. Unfortuately, that would often occur after the rest of the test had finished in the main thread and my object was destroyed. This could be because the emulator is too busy to process the UIEvent before the test continues.

I was able to fix this problem by using a CyclicBarrier to ensure that my test did not continue until after the code was run in the UiThread. I created a method to encapuslate this and use this instead of Activity.runOnUiThread() in my tests:

  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(); }
  }

This is how it looks in my test class:

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);

Upvotes: 3

gregory561
gregory561

Reputation: 15046

This exception is mostly caused by another exception that is thrown when your activity is started. Because of it the activity is not created and you get NullPointException. Try to debug your tests by setting a breakpoint in place where you for the first time invoke the getActivity() and find a bug in your code.

Upvotes: 0

Karl Zoller
Karl Zoller

Reputation: 11

I had the same problem as well as a few other strange null pointer exceptions. Strangely this seemed to have something to do with having static member variables in the testing class.

As soon as I removed the static keywords from the variables then all issues were resolved. It doesn't make any sense since the variables had nothing to do with the line of code that was causing the exception in the first place.

But all works now...

Upvotes: 1

Arnoud
Arnoud

Reputation: 235

Don't ask me why, but if you add at least one sendKey() to your code it works:

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);
}

Upvotes: 1

Bendik
Bendik

Reputation: 928

Ok, so it seems I got it working now. At least to a certain point. I am still not able to run anything inside runOnUiThread(), but I found that using the @UiThreadTest annotation gave me satisfactory results. I no longer get NullPointerExceptions, and the setUp() method even runs correctly. I have no idea what was causing this, but hey, at least it is working :)

Upvotes: 6

Related Questions