用机器电学测试 ViewPager (和 CursorLoader)

有人知道如何使用 Robolecric 测试下面的设置吗?

包含 ViewPager 的片段,用 CursorLoader 加载的数据。

使用下面的代码,CursorLoader 永远不会被推送到视图页导航器的适配器中。 我被 await()的电话缠住了。

事件片段测试.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;
}


}

事件片段.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);
}
}
4066 次浏览

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.