是否可以使用robolectric将测试对象替换为MediaStore?

我有一个查询MediaStore图像的类。 例如,我的代码看起来像someContentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ... ) 。 我想测试一下,我对MediaStore的查询是正确的。

到目前为止我在测试中所做的是:

 ContentResolver resolver = new Activity().getContentResolver(); ContentValues values = new ContentValues(); values.put( MediaStore.Images.Media.DATA, "/fake/path/file1.jpg" ); values.put( MediaStore.Images.Media.DATE_ADDED, fakeTime.getTime() ); resolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values ); 

我将这个解析器注入我的类,它对它执行查询。 但是,查询返回null。 我看到这篇文章: http : //ikaruga2.wordpress.com/2013/07/29/roboelectric-and-contentresolverscontentproviders/ ,它说要使用ShadowContentResolver注册内容提供者,所以,如下所示:

 ShadowContentResolver.registerProvider( MediaStore.AUTHORITY,  ); 

但我不知道该为内容提供商提供什么。 也许使用MediaStore对象? 不,它不是ContentProvider 。 也许是MediaProvider ? 由于某种原因,该符号无法解析。

在这一点上,我严重怀疑这是远程正确的方法。 有人能引导我朝着正确的方向前进吗?

使用Robolectric 2.4快照和API 19。

您可以依靠ShadowContentResolver.setCursor(Uri, BaseCursor)RoboCursor来创建测试数据并validation查询。 RoboCursor不提供一些方法的完整实现,因此您可以覆盖和忽略它们,或者做一些有意义的事情。 RoboCursor扩展了BaseCursor ,覆盖了setQuery()允许您拦截查询并validation或执行某些操作。 使用Robolectric 3.0。

 RoboCursor cursor = new RoboCursor() { @Override public void registerContentObserver(ContentObserver observer) { // no op } @Override public void unregisterContentObserver(ContentObserver observer) { // no op } @Override public void registerDataSetObserver(DataSetObserver observer) { // no op } @Override public void unregisterDataSetObserver(DataSetObserver observer) { // no op } @Override public boolean isClosed() { return true; } }; cursor.setColumnNames(Arrays.asList(MediaStore.Images.Media._ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); cursor.setResults(new Object[][]{ new Object[]{1L, "WhatsApp"}, new Object[]{2L, "Photos"}, new Object[]{3L, "WhatsApp"} }); shadowOf(ShadowApplication.getInstance().getContentResolver()) .setCursor(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor); 

我在MediaStore遇到了类似的问题,在我的例子中,一个类试图通过managedQuery访问MediaStore。 运行经过此类代码路径的测试时,测试因NPE失败,因为查询返回null就像您的情况一样。

违规方法

 public String getPath(Uri uri, Activity activity) { String[] projection = { MediaColumns.DATA }; Cursor cursor = activity .managedQuery(uri, projection, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } 

鉴于你已经注入(我在我的项目上注入Dagger依赖项)解析器,你可能想要模拟它,如果它适合你(例如通过Mockito),或者部分模拟它,那么违规方法默认是可用的返回值。

 PhotoUtilities pu=Mockito.spy(new PhotoUtilities()); Mockito.doReturn(Constants.getDataDir().getAbsolutePath()+"/aaa.txt"). when(pu).getPath(Mockito.isA(Uri.class), Mockito.isA(Activity.class)); 

这样,当测试尝试运行getPath() ,它不会运行查询,而是使用部分模拟中设置的默认返回值,允许测试继续。

我知道它可能不是你正在寻找的东西,但它可能适合你的需要,就像它对我一样。