使用Robolectric和Mockito测试CursorLoader

Seb*_*oth 7 android mockito robolectric

鉴于我正在开发一个简单的ListFragment(在这种情况下,它从MediaStore读取艺术家列表,但稍后也将从不同的源读取数据),如下所示:

@EFragment
public class ArtistsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
    private static final String TAG = ArtistsFragment.class.getName();
    private SimpleCursorAdapter mAdapter;

    Uri uri = MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI;

    CursorLoader mCursorLoader;

    @AfterViews
    void setupView() {
        mAdapter = new SimpleCursorAdapter(getActivity(),
                android.R.layout.simple_list_item_1, null,
                new String[]{MediaStore.Audio.Artists.ARTIST}, // lists path of files
                new int[]{android.R.id.text1}, 0);

        setListAdapter(mAdapter);

        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        if (mCursorLoader == null) {
            mCursorLoader = new CursorLoader(getActivity(), uri, new String[]{MediaStore.Audio.Artists._ID, MediaStore.Audio.Artists.ARTIST},
                    null, null, MediaStore.Audio.Artists.ARTIST + " ASC");
        } else {
            System.out.println("mCursorLoader.count: " + mCursorLoader.loadInBackground().getCount());            
        }
        return mCursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        setListShown(true);
        mAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mAdapter.swapCursor(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想使用Robolectric + Mockito + awaitility来证明Fragment在各种条件下表现正常(例如空列表或无效数据等).我的测试类看起来像这样:

@RunWith(RobolectricTestRunner.class)
public class ArtistsFragmentTest {
    @Test
    public void shouldNotBeNull() {
        final ArtistsFragment myFragment = ArtistsFragment_.builder().build();
        assertNotNull(myFragment);

        // Create a mock cursor.
        final Cursor mc = getSampleArtistCursor();
        when(mc.getCount()).thenReturn(1);
        when(mc.getInt(0)).thenReturn(1);
        when(mc.getString(1)).thenReturn("Sample Title");

        myFragment.mCursorLoader = mock(CursorLoader.class);
        when(myFragment.mCursorLoader.loadInBackground()).thenReturn(mc);

        startFragment(myFragment);

        assertNotNull(myFragment.getListView());
        await().atMost(5, TimeUnit.SECONDS).until(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return myFragment.getListAdapter().getCount();
            }
        }, equalTo(1));

        System.out.println(myFragment.getListAdapter().getCount());
    }

    private Cursor getSampleArtistCursor() {
        return new CursorWrapper(mock(MockCursor.class));
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当在IntelliJ或maven中运行此测试时,测试将失败,适配器将始终返回零计数.

然而,onCreateLoader中的System.out.println语句返回1.我是否需要在背景线程中特别注意Mockito ?(loadInBackground方法在工作线程上运行).

Seb*_*oth 1

解决方案是使用:

Robolectric.flushForegroundThreadScheduler();
Run Code Online (Sandbox Code Playgroud)

(机器人电动3.0)

这将立即运行所有任务,包括CursorLoader