我在仅使用SQLite的ContentProvider上进行了大约十次测试; all pass保存在Content Provider的query()方法中通过queryBuilder.query()的两个。
正在测试的方法在实际应用中起作用!
这是API 17 r2和RoboLectric: robolectric-2.0-α-3-20130417.013705-46-罐与 - dependencies.jar
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.d(Constants.TAG, "MyContentProvider.query()");
switch(matcher.match(uri)) {
case ITEM: // OK
selection = "_id = ?";
selectionArgs = new String[]{ Long.toString(ContentUris.parseId(uri)) };
case ITEMS: // OK
break;
default:
throw new IllegalArgumentException("Did not recognize URI " + uri);
}
// build the query with SQLiteQueryBuilder
SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
qBuilder.setTables(TABLE_NAME);
// query the database and get result in cursor
final SQLiteDatabase db = mDatabase.getReadableDatabase();
Cursor resultCursor = qBuilder.query(db, // Line 112 in trace
projection, selection, selectionArgs, null, null, sortOrder,
null);
resultCursor.setNotificationUri(getContext().getContentResolver(), uri);
return resultCursor;
}
这是追溯:
java.lang.RuntimeException: java.lang.InstantiationException
at org.robolectric.bytecode.ShadowWrangler.createShadowFor(ShadowWrangler.java:300)
at org.robolectric.bytecode.ShadowWrangler.initializing(ShadowWrangler.java:74)
at org.robolectric.bytecode.RobolectricInternals.initializing(RobolectricInternals.java:90)
at android.database.sqlite.SQLiteQuery.$$robo$init(SQLiteQuery.java)
at android.database.sqlite.SQLiteClosable.<init>(SQLiteClosable.java:26)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:41)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:400)
at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:333)
at com.example.readingsprovider.ReadingsContentProvider.query(ReadingsContentProvider.java:112)
at com.example.readingsprovider.test.ContentProviderTest.testUpdateMultipleWithoutWhere(ContentProviderTest.java:110)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:267)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:202)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:310)
at org.robolectric.bytecode.ShadowWrangler.createShadowFor(ShadowWrangler.java:293)
at org.robolectric.bytecode.ShadowWrangler.initializing(ShadowWrangler.java:74)
at org.robolectric.bytecode.RobolectricInternals.initializing(RobolectricInternals.java:90)
at android.database.sqlite.SQLiteQuery.$$robo$init(SQLiteQuery.java)
at android.database.sqlite.SQLiteClosable.<init>(SQLiteClosable.java:26)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:41)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.$$robo$$SQLiteDirectCursorDriver_7ac1_query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java)
at android.database.sqlite.SQLiteDatabase.$$robo$$SQLiteDatabase_ab15_rawQueryWithFactory(SQLiteDatabase.java:1314)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java)
at android.database.sqlite.SQLiteQueryBuilder.$$robo$$SQLiteQueryBuilder_ba4d_query(SQLiteQueryBuilder.java:400)
at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java)
at android.database.sqlite.SQLiteQueryBuilder.$$robo$$SQLiteQueryBuilder_ba4d_query(SQLiteQueryBuilder.java:333)
at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java)
at com.example.readingsprovider.ReadingsContentProvider.query(ReadingsContentProvider.java:112)
at com.example.readingsprovider.test.ContentProviderTest.testUpdateMultipleWithoutWhere(ContentProviderTest.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
... 21 more
可以告诉我这是Robolectric的限制,还是我的坏?非常感谢!
P.S。如果Reflection API将失败的类名放在InstantiationException消息中,这不是很梦幻吗?
答案 0 :(得分:6)
我的项目遇到了同样的问题,终于能够用一些谷歌搜索和U Avalos的前一个答案来解决它了
@Implements(value = SQLiteDatabase.class, inheritImplementationMethods = true)
public class CustomSQLiteShadow extends ShadowSQLiteDatabase {
@Implementation
public Cursor rawQueryWithFactory (SQLiteDatabase.CursorFactory cursorFactory,
String sql,
String[] selectionArgs,
String editTable,
CancellationSignal cancellationSignal) {
return rawQueryWithFactory(cursorFactory,
sql,
selectionArgs,
editTable);
}
}
@Config
注释要使用自定义阴影类,可以在robolectric2中使用@Config
注释
@RunWith(RobolectricTestRunner.class)
@Config( shadows = {CustomSQLiteShadow.class})
public class ContentProviderTest {
http://robolectric.blogspot.co.at/2013/05/configuring-robolectric-20.html
答案 1 :(得分:2)
Android API 16引入了这种新方法(mtholdefer提到):
public Cursor rawQueryWithFactory (SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal)
截至2013年7月25日,roboelectric并未实施此方法。但是,它实现了一种不使用CancellationSignal的类似方法。将此方法添加到ShadowSqlLiteDatabase使我的问题消失了:
@Implementation
public Cursor rawQueryWithFactory (SQLiteDatabase.CursorFactory cursorFactory,
String sql,
String[] selectionArgs,
String editTable,
CancellationSignal cancellationSignal)
{
return rawQueryWithFactory(cursorFactory,
sql,
selectionArgs,
editTable);
}
(是的,你需要将roboelectric作为子模块。)
答案 2 :(得分:1)
我遇到了类似的问题,我认为问题在于Robolectric不支持SQLiteQueryBuilder。您可以阅读有关here的更多信息。基本上,SQLiteQueryBuilder使用的rawQueryWithFactor()方法不会在ShadowSQLiteDatabase中被覆盖。因此,cusor返回为null
我刚开始通过SQLiteDatabaseInstance.query实例化我的游标,并且与Robolectric结合使用。祝你好运,如果你找到更优雅的解决方案,请告诉我,我也可以测试我的queryBuilders!