问题描述
有谁知道如何使用Robolectric测试以下设置?
含有ViewPager片段,数据加载有CursorLoader
通过下面的code时,CursorLoader永远不会被推入该视图寻呼机适配器。我陷在等待()
电话。
EventsFragmentTest.java:
@RunWith(CustomRobolectricTestRunner.class)
公共类EventsFragmentTest扩展AbstractDbAndUiDriver
{
//该元素在视图中寻呼机我们正在测试
私有静态最终诠释的test_index = 0;
保护SherlockFragmentActivity mActivity;
保护EventsFragment_ mFragment;
@覆盖
@之前
公共无效设置()抛出异常
{
//创建活动举行片段
this.mActivity = CustomRobolectricTestRunner.getActivity();
//创建并启动片段
this.mFragment =新EventsFragment_();
}
@测试
公共无效sanityTest()
{
//创建一个事件
最终事件事件= this.createEvent();
//创建模拟光标装载机
最后光标光标= this.createMockEventCursor(事件);
this.mFragment.setCursorLoader(模拟(CursorLoader.class));
当(this.mFragment.getCursorLoader()loadInBackground()。)thenReturn(光标)。
CustomRobolectricTestRunner.startFragment(this.mActivity,this.mFragment);
等待()atMost(5秒)。直到(this.isCursorLoaderLoaded(),equalTo(真))。
//检查显示的数据
最后的TextView标题= this.getTextView(R.id.event_view_title);
最后的TextView文本= this.getTextView(R.id.event_view_text);
//存在,可见是足够了
this.getImageView(R.id.event_view_image);
assertThat(title.getText()的toString(),equalTo(event.getTitle())。);
assertThat(text.getText()的toString(),是(event.getText()));
// 清理
cursor.close();
}
@覆盖
受保护的视图getRootView()
{
返程((ViewPager)this.mFragment.getView()findViewById(R.id.events_pager)。)getChildAt(的test_index)。
}
私人可赎回<布尔> isCursorLoaderLoaded()
{
回到新的可赎回<布尔>()
{
公共布尔调用()抛出异常
{
返回EventsFragmentTest.this.mFragment.isCursorLoaderLoaded(); //所必须满足的条件
}
};
}
/ **
*创建一个事件
*
* @返回
* /
保护事件CreateEvent的()
{
//创建一个随机事件
最终事件事件=新的事件();
event.setImage(空);
event.setLink(/一些/链接/+ RandomUtils.getRandomString(5)); // $ NON-NLS-1 $
event.setResourceUri(/ REST / URI /+ RandomUtils.getRandomDouble()); // $ NON-NLS-1 $
event.setText(这是一个测试对象+ RandomUtils.getRandomString(5)); // $ NON-NLS-1 $
回到事件;
}
受保护的光标createMockEventCursor(最终事件的事件)
{
//创建一个模拟指针。
最后光标光标=新CursorWrapper(模拟(MockCursor.class));
当(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());
当(cursor.getString(cursor.getColumnIndexOrThrow(EventTable.COLUMN_RESOURCE_URI)))。thenReturn(
event.getResourceUri());
//创建收益事件
返回游标;
}
}
EventsFragment.java
@EFragment(resName =events_fragment)
公共类EventsFragment扩展SherlockFragment实现LoaderCallbacks<光标>
{
@ViewById(R.id.events_pager)
保护ViewPager mPager;
@ViewById(R.id.events_indicator)
保护CirclePageIndicator mIndicator;
@ preF
保护IShared prefs_米preferences;
保护EventsFragmentAdapter pageAdapter;
私人CursorLoader mCursorLoader;
/ **
*初始化的CursorAdapter和光标管理器装载器。
* /
@AfterViews
无效的init()
{
最终SherlockFragmentActivity活性= this.getSherlockActivity();
this.pageAdapter =新EventsFragmentAdapter(activity.getSupportFragmentManager(),NULL);
this.mPager.setAdapter(this.pageAdapter);
this.mIndicator.setViewPager(this.mPager);
。this.getLoaderManager()initLoader(this.mPager.getId(),null,则此);
}
/ *(非Javadoc中)
* @see android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(INT,android.os.Bundle)
* /
@覆盖
公共装载机<光标> onCreateLoader(最终诠释为arg0,最终捆绑ARG1)
{
如果(this.mCursorLoader == NULL)
{
//设置排序最新第一
最后弦乐排序顺序= BaseColumns._ID +DESC; // $ NON-NLS-1 $
this.mCursorLoader =新CursorLoader(this.getActivity(),EventContentProvider.CONTENT_URI,
EventTable.getProjection(),AbstractDbTable.getWhereCondition(空)
AbstractDbTable.getWhereArgs(this.m preferences,空),排序顺序);
}
返回this.mCursorLoader;
}
/ *(非Javadoc中)
* @看到android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android.support.v4.content.Loader,的java.lang.Object)
* /
@覆盖
公共无效onLoadFinished(最终装载机<光标>为arg0,最后光标光标)
{
this.pageAdapter.swapCursor(光标);
}
/ *(非Javadoc中)
* @看到android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset(android.support.v4.content.Loader)
* /
@覆盖
公共无效onLoaderReset(最终装载机<光标>为arg0)
{
this.pageAdapter.swapCursor(空);
}
/ **
*为必填仅供测试。
*
* @参数cursorLoader
* /
公共无效setCursorLoader(最终CursorLoader cursorLoader)
{
this.mCursorLoader = cursorLoader;
}
/ **
*为必填仅供测试。
*
* @参数cursorLoader
* /
公共CursorLoader getCursorLoader()
{
返回this.mCursorLoader;
}
公共布尔isCursorLoaderLoaded()
{
返回(this.pageAdapter.getCursor()!= NULL);
}
}
我不能肯定,但我敢打赌,内部code正试图用一个 的AsyncTask
执行光标加载程序的 loadInBackground()
方法。您可能会看到一个僵局,因为在 的AsyncTask
试图调用 onPostExecute()
。该通话将尝试在主UI线程,这恰好是你的测试程序的线程中运行。这可能永远不会发生,因为你是停留在观望与调用堆栈上的测试程序。
尝试将你的嘲讽到一个更高的水平,使没有真正发生在从测试的背景。谷歌的`AsyncTask的单元测试机器人的僵局可以看到的例子,其他人遇到了类似的问题。
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);
}
}
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.
这篇关于测试ViewPager(和CursorLoader)与Robolectric的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!