Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing ViewPager (and CursorLoader) with Robolectric

Does anyone know how to test the following setup using Robolectric?

Fragment containing a ViewPager, data loaded with a CursorLoader.

With the code below, the CursorLoader is never pushed into the adapter for the view pager. I get stuck at the await() call.

EventsFragmentTest.java:

@RunWith(CustomRobolectricTestRunner.class) public class EventsFragmentTest extends AbstractDbAndUiDriver {     // which element in the view pager we are testing     private static final int           TEST_INDEX = 0;      protected SherlockFragmentActivity mActivity;     protected EventsFragment_          mFragment;      @Override     @Before     public void setUp() throws Exception     {         // create activity to hold the fragment         this.mActivity = CustomRobolectricTestRunner.getActivity();          // create and start the fragment         this.mFragment = new EventsFragment_();     }      @Test     public void sanityTest()     {         // create an event         final Event event = this.createEvent();          // create mock cursor loader         final Cursor cursor = this.createMockEventCursor(event);         this.mFragment.setCursorLoader(mock(CursorLoader.class));         when(this.mFragment.getCursorLoader().loadInBackground()).thenReturn(cursor);         CustomRobolectricTestRunner.startFragment(this.mActivity, this.mFragment);          await().atMost(5, SECONDS).until(this.isCursorLoaderLoaded(), equalTo(true));          // check for data displayed         final TextView title = this.getTextView(R.id.event_view_title);         final TextView text = this.getTextView(R.id.event_view_text);          // exists and visible is enough for now         this.getImageView(R.id.event_view_image);          assertThat(title.getText().toString(), equalTo(event.getTitle()));         assertThat(text.getText().toString(), is(event.getText()));          // clean up         cursor.close();     }      @Override     protected View getRootView()     {         return ((ViewPager) this.mFragment.getView().findViewById(R.id.events_pager)).getChildAt(TEST_INDEX);     }      private Callable<Boolean> isCursorLoaderLoaded()     {         return new Callable<Boolean>()         {             public Boolean call() throws Exception             {                 return EventsFragmentTest.this.mFragment.isCursorLoaderLoaded(); // The condition that must be fulfilled             }         };     }      /**      * Create an event      *       * @return      */     protected Event createEvent()     {         // create a random event         final Event event = new Event();         event.setImage(null);         event.setLink("/some/link/" + RandomUtils.getRandomString(5)); //$NON-NLS-1$         event.setResourceUri("/rest/uri/" + RandomUtils.getRandomDouble()); //$NON-NLS-1$         event.setText("this is a test object " + RandomUtils.getRandomString(5)); //$NON-NLS-1$         return event;     }      protected Cursor createMockEventCursor(final Event event)     {         // Create a mock cursor.         final Cursor cursor = new CursorWrapper(mock(MockCursor.class));          when(cursor.getCount()).thenReturn(1);         when(cursor.getString(cursor.getColumnIndexOrThrow(EventTable.COLUMN_TEXT))).thenReturn(event.getText());         when(cursor.getString(cursor.getColumnIndexOrThrow(EventTable.COLUMN_TITLE))).thenReturn(event.getTitle());         when(cursor.getString(cursor.getColumnIndexOrThrow(EventTable.COLUMN_IMAGE))).thenReturn(event.getImage());         when(cursor.getString(cursor.getColumnIndexOrThrow(EventTable.COLUMN_LINK))).thenReturn(event.getLink());         when(cursor.getString(cursor.getColumnIndexOrThrow(EventTable.COLUMN_RESOURCE_URI))).thenReturn(                         event.getResourceUri());          // return created event         return cursor;     }  } 

EventsFragment.java

@EFragment(resName = "events_fragment") public class EventsFragment extends SherlockFragment implements LoaderCallbacks<Cursor> {     @ViewById(R.id.events_pager)     protected ViewPager             mPager;      @ViewById(R.id.events_indicator)     protected CirclePageIndicator   mIndicator;      @Pref     protected ISharedPrefs_         mPreferences;      protected EventsFragmentAdapter pageAdapter;      private CursorLoader            mCursorLoader;      /**      * initialise the cursoradapter and the cursor loader manager.      */     @AfterViews     void init()     {         final SherlockFragmentActivity activity = this.getSherlockActivity();          this.pageAdapter = new EventsFragmentAdapter(activity.getSupportFragmentManager(), null);         this.mPager.setAdapter(this.pageAdapter);         this.mIndicator.setViewPager(this.mPager);         this.getLoaderManager().initLoader(this.mPager.getId(), null, this);     }      /* (non-Javadoc)      * @see android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int, android.os.Bundle)      */     @Override     public Loader<Cursor> onCreateLoader(final int arg0, final Bundle arg1)     {         if (this.mCursorLoader == null)         {             // set sort to newest first             final String sortOrder = BaseColumns._ID + " DESC"; //$NON-NLS-1$              this.mCursorLoader = new CursorLoader(this.getActivity(), EventContentProvider.CONTENT_URI,                             EventTable.getProjection(), AbstractDbTable.getWhereCondition(null),                             AbstractDbTable.getWhereArgs(this.mPreferences, null), sortOrder);         }         return this.mCursorLoader;     }      /* (non-Javadoc)      * @see android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android.support.v4.content.Loader, java.lang.Object)      */     @Override     public void onLoadFinished(final Loader<Cursor> arg0, final Cursor cursor)     {         this.pageAdapter.swapCursor(cursor);      }      /* (non-Javadoc)      * @see android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset(android.support.v4.content.Loader)      */     @Override     public void onLoaderReset(final Loader<Cursor> arg0)     {         this.pageAdapter.swapCursor(null);     }      /**      * Required for testing only.      *       * @param cursorLoader      */     public void setCursorLoader(final CursorLoader cursorLoader)     {         this.mCursorLoader = cursorLoader;     }      /**      * Required for testing only.      *       * @param cursorLoader      */     public CursorLoader getCursorLoader()     {         return this.mCursorLoader;     }      public boolean isCursorLoaderLoaded()     {         return (this.pageAdapter.getCursor() != null);     } } 
like image 950
Corey Scott Avatar asked Dec 03 '13 08:12

Corey Scott


1 Answers

I'm not certain, but I would wager that the internal code is trying to use an AsyncTask to invoke the cursor loader's loadInBackground() method. You might be seeing a deadlock because the AsyncTask tries to invoke onPostExecute(). That call will try to run in your main UI thread, which happens to be the thread of your test routine. That can never happen because you are stuck in a wait with your test routine on the call stack.

Try moving your mocking up to a higher level so that nothing really happens in the background from the test. google `AsyncTask unit test android deadlock' to see examples where other people ran into similar problems.

like image 115
bigh_29 Avatar answered Sep 22 '22 17:09

bigh_29