Robolectric + SQLiteStatement.executeUpdateDelete(

2019-07-27 08:18发布

I'm need to increment some integer in table. Instead of making select and consecutive update, i'm want to do this by single query. But out of luck.

Following code returns 0:

final SQLiteStatement stmt = helper.getWritableDatabase().
    compileStatement("update my_table set my_count = my_count + 1 where _id = ?");
try
{
    stmt.bindLong(1, id);
    return stmt.executeUpdateDelete();
}
finally
{
    stmt.close();
}

And, of course, no record is updated.

But this returns 1:

final ContentValues v = new ContentValues();
v.put("my_count", 1);
return helper.getWritableDatabase().
    update("my_table", v, "_id=?", new String[]{String.valueOf(id)});

Record with specified id is 100% exists. Tried to make this within or without transaction - result is same. Didn't test on real SQLiteStatement, probably Robolectric bug.

Anybody has any assumptions regarding this effect? Or suggestions about how to get around this problem (may be without usage of SQLiteStatement)?

Thanks.

Update 1.

I'm also roll some simple test:

@RunWith(RobolectricTestRunner.class)
public class SQLiteStatementTest
{

    private static class TestOpenHelper extends SQLiteOpenHelper
    {
        public TestOpenHelper(Context context)
        {
            super(context, "test", null, 1);
        }

        @Override
        public void onCreate(SQLiteDatabase db)
        {
            db.execSQL("CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREMENT, count INTEGER)");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        {
        }
    }

    @Test
    public void testExecuteUpdateDeleteModifiesRow() throws Exception
    {
        final int initialCount = 6;
        final TestOpenHelper helper = new TestOpenHelper(Robolectric.application);

        final ContentValues v = new ContentValues();
        v.put("count", initialCount);
        final long id = helper.getWritableDatabase().insert("test", null, v);

        final SQLiteStatement stmt = helper.getWritableDatabase().
            compileStatement("update test set count = count + 1 where _id=?");

        stmt.bindLong(1, id);
        assertThat(stmt.executeUpdateDelete(), is(1));

    }
}

1条回答
家丑人穷心不美
2楼-- · 2019-07-27 08:55

According to following sources:

https://github.com/pivotal/robolectric/blob/master/src/main/java/org/robolectric/shadows/ShadowSQLiteStatement.java

executeUpdateDelete() isn't implemented.

Since callThroughByDefault = false this method is shadowed by default empty implementation. This is why i don't get RuntimeException("Stub!").

It should be very easy to shadow this method, but i found a more general problem (with Uri.parse method) in robolectric 2.0-alpha-2

Update 1.

Pull requests to shadow executeUpdateDelete():
https://github.com/pivotal/robolectric/pull/450
https://github.com/pivotal/robolectric/pull/451

查看更多
登录 后发表回答