Android Content Provider奇怪行为测试
问题描述:
我写了一个ContentProvider来处理本地sqlite数据库上的query/insert/update/delete
。Android Content Provider奇怪行为测试
出于测试目的,我写了几个测试:
TestMovieContract.java : for testing MovieContract class
TestMovieDBHelper.java : for testing MovieDBHelper class
TestUriMatcher.java : for testing UriMatcher inside MovieContentProvider class
TestProvider.java : for testing MovieContentProvider class
当我单独运行这些测试,他们都获得通过,但是当我运行所有这些测试的一个失败。它失败的断言语句是:
returnedUri = mContext.getContentResolver().insert(
movieInsertUri,
sampleMovieValues
);
assertNotNull("the values have not been inserted into " + MovieContract.MovieEntry.TABLE_NAME, returnedUri);
当我检查执行这个特定的测试,当我看到一个异常的logcat:
04-24 19:16:00.086 6938-6963/com.example.android.popularmovies.app I/TestRunner: started: testAndroidTestCaseSetupProperly(com.example.android.popularmovies.app.data.TestProvider)
04-24 19:16:00.104 6938-6963/com.example.android.popularmovies.app I/TestRunner: finished: testAndroidTestCaseSetupProperly(com.example.android.popularmovies.app.data.TestProvider)
04-24 19:16:00.104 6938-6963/com.example.android.popularmovies.app I/TestRunner: passed: testAndroidTestCaseSetupProperly(com.example.android.popularmovies.app.data.TestProvider)
04-24 19:16:00.104 6938-6963/com.example.android.popularmovies.app I/TestRunner: started: testDelete(com.example.android.popularmovies.app.data.TestProvider)
04-24 19:16:00.122 6938-6963/? E/SQLiteLog: (1032) statement aborts at 33: [INSERT INTO movie(popularity,vote_average,original_title,backdrop_url,movie_id,original_lang,image_url,overview,title,is_adult,release_date,vote_count,is_favorite,genre_ids) VALUES (?,
04-24 19:16:00.122 6938-6963/? E/SQLiteDatabase: Error inserting popularity=8.3 vote_average=5.2 original_title=Some Android backdrop_url=http://mybackimage.com/44.png movie_id=40443 original_lang=en image_url=http://someimage.com/33.jpg overview=This is a sample overview title=Very First Android is_adult=true release_date=2015-05-23 vote_count=33345 is_favorite=true genre_ids=23,1,5
android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:780)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1471)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
at com.example.android.popularmovies.app.data.MovieContentProvider.insert(MovieContentProvider.java:197)
at android.content.ContentProvider$Transport.insert(ContentProvider.java:263)
at android.content.ContentResolver.insert(ContentResolver.java:1231)
at com.example.android.popularmovies.app.data.TestProvider.testDelete(TestProvider.java:308)
at java.lang.reflect.Method.invoke(Native Method)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:115)
at junit.framework.TestResult.runProtected(TestResult.java:133)
at junit.framework.TestResult.run(TestResult.java:118)
at junit.framework.TestCase.run(TestCase.java:124)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1879)
04-24 19:16:00.122 6938-6963/? W/SQLiteLog: (28) file unlinked while open: /data/user/0/com.example.android.popularmovies.app/databases/movie.db
有一个在这篇日志,我认为年底的警告很重要。它显示数据库文件未链接。我检查了我的所有代码,以查看任何数据库连接的正确关闭。
我的问题是为什么当我运行TestProvider.java
时测试通过,但是当我运行所有这些时失败了?我该如何解决它?
UPDATE
我做了小改动的地方我断言失败的面积和克隆的插入语句。新代码如下所示:
returnedUri = mContext.getContentResolver().insert(
movieInsertUri,
sampleMovieValues
);
returnedUri = mContext.getContentResolver().insert(
movieInsertUri,
sampleMovieValues
);
assertNotNull("the values have not been inserted into " + MovieContract.MovieEntry.TABLE_NAME, returnedUri);
令人惊讶的所有测试都通过,使我觉得有可能的东西引擎盖下是错误的。我很感激,如果有人能帮助我搞清楚了这一点
答
问题可以用的ContentProvider的多个实例,使用ContentProvider.shutdown();
“当你调用一个ContentProvider的测试方法,但是,ContentProvider的实例启动后继续运行即使后续测试实例化另一个ContentProvider,也会产生冲突,因为这两个实例通常针对相同的基础数据源(例如,sqlite数据库)运行“
检查docs。
例子:
@Override
@TargetApi(11)
public void shutdown() {
mOpenHelper.close();
super.shutdown();
}
答
实现关机()为马克西姆摹提到确实需要照顾的问题,但你需要确保你的代码调用它在每个测试。棘手的部分是通过ContentResolver访问ContentProvider。
mContext.getContentResolver()
.acquireContentProviderClient(uri)
.getLocalContentProvider()
.shutdown();
只要您的内容供应商不是外部供应商,这种方法就行得通。
你使用模拟器还是真实设备?它是否植根?它有多少内存? –
@MaximG模拟1G内存 – Pooya