2

I just created unit tests for my CRUD implementations and I have this weird problem. When tests are run one by one, they all pass. But when I want to run the whole suite, they fail with the error

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:782)
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.insertOrThrow(SQLiteDatabase.java:1367)
at cz.pikadorama.simpleorm.DatabaseSanityTest.testDelete(DatabaseSanityTest.java:55)

Here's the code

@Before
public void prepareDatabase() throws InstantiationException, IllegalAccessException {
    Context context = InstrumentationRegistry.getTargetContext();
    context.deleteDatabase(DATABASE_NAME);
    DbManager.registerHelper(new TestSQLiteHelper(context), new Class<?>[]{TestEntity.class});
}

@Test
public void testDelete() {
    Dao<TestEntity> dao = DaoManager.getDao(TestEntity.class);
    TestEntity entity = new TestEntity();
    dao.create(entity);  
    dao.delete(entity);
    assertEquals(0, dao.findAll().size());
}

// other tests for insert, update, ... follow

By the way, DAO implementations always open writable database as sqliteOpenHelper.getWritableDatabase().

4
  • Are you closing the database at any point between your tests? Commented Oct 29, 2016 at 18:27
  • 1
    Try to change your current @Before method into @BeforeClass method. Does it resolve the issue? Commented Oct 29, 2016 at 18:38
  • Yes, in the end I tried to move the prepare to @BeforeClass and cleaned the database instead of deleting it before each test. Commented Oct 29, 2016 at 18:44
  • So, it did resolve the issue, right? Commented Oct 29, 2016 at 18:46

1 Answer 1

1

It is related to the fact that DbManager and DaoMaster are singletons (as well as the underlying database, I suppose): the code in @Before is called before each test, which screws up things in classes which, probably, should be initiated just once.

Change @Before annotation to @BeforeClass in order to perform the initialization just once.

Sign up to request clarification or add additional context in comments.

2 Comments

Well, that's not the problem. The issue is that when you have delete database in @Before and you run it each time, the tests are so fast the actually there is a 'hot journal' that needs to be written. But by default the Java connection is created as read-only and you cannot write the journal with that connection.
@user219882, I think you are mistaken. You can delete database in @Before, but then you must make sure that you also initialize it properly again. I do think that the issue in your case was the fact that a call to DbManager.registerHelper() did not do the initialization properly. In any case, since this answer resolved your issue, consider accepting it )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.