Robolectric で Content Provider をテストする


概要

Robolectric を使って、自作の Content Provider をテストする方法

注意事項

この記事はRobolectric Version 3.8 の使用を前提にしています。
Version 4.0 以後、あるいは、Version 3.3以前ではAPIが変わっていると思います。

コード例

ItemProvider.kt
class ItemProvider : ContentProvider() {

    private lateinit var openHelper: MyDatabaseHelper

    override fun onCreate(): Boolean {
        openHelper = MyDatabaseHelper(context, "mydb", null, 1)
        return true
    }

    override fun insert(uri: Uri, values: ContentValues): Uri? {
        val db = openHelper.writableDatabase
        val i = db.insert("main", null, values)
        return ContentUris.withAppendedId(uri, i)
    }

    override fun query(uri: Uri, projection: Array<String>?, selection: String?,
                       selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
        val db = openHelper.readableDatabase
        return db.query("main", projection, selection, selectionArgs, null, null, null)
    }

    // 以下コンテンツプロバイダで実装必須なメソッドが並ぶ
}

上の例は自作コンテンツプロバイダの例です。
内部ではSQLiteのデータベースを使っています。
以下の表のような、商品と値段のデータを保存するコンテンツプロバイダとします。

_id ITEM PRICE
1 apple 100
2 banana 200

このコンテンツプロバイダに対するテストクラスの例は、以下のコードです。

ItemProviderTest.kt

class ItemProviderTest {

    private var resolver: ContentResolver? = null

    @Before
    fun setUp() {
        resolver = RuntimeEnvironment.application.contentResolver
    }

    private fun insertApple() {
        val values = ContentValues()
        values.put(ItemContract.Items.ITEM, "apple")
        values.put(ItemContract.Items.PRICE, 100)
        resolver?.insert(ItemContract.Items.CONTENT_URI, values)
    }

    @Test
    fun insertAndQueryApple() {
        insertApple()
        val projection = arrayOf(ItemContract.Items.ITEM, ItemContract.Items.PRICE)
        val selection = "${ItemContract.Items.ITEM} = ?"
        val selectionArgs = arrayOf("apple")
        val cursor = resolver?.query(
                ItemContract.Items.CONTENT_URI,
                projection,
                selection,
                selectionArgs,
                null)
        cursor?.use {
            it.moveToNext()
            val index = it.getColumnIndex(ItemContract.Items.PRICE)
            val price = cursor.getInt(index)
            assertEquals(100, price)
        }
    }
}

Robolectric を使っているので、このテストはAndroid実機ではないJVM上で実行できます。