How to test class using content resolver/provider?

Viewed 13702

I'm trying to test class that queries content resolver.

I would like to use MockContentResolver and mock query method.

The problem is that this method is final. What should I do? Use mocking framework? Mock other class? Thanks in advance.

public class CustomClass {

    private ContentResolver mContentResolver;

    public CustomClass(ContentResolver contentResolver) {
        mContentResolver = contentResolver;
    }

    public String getConfig(String key) throws NoSuchFieldException {
        String value = null;

            Cursor cursor = getContentResolver().query(...);
            if (cursor.moveToFirst()) {
                //...
            }
        //..
    }
}
5 Answers

Here is an example about how to stub a ContentResolver with mockk Library and Kotlin.

NOTE: this test seems that is not working if you run this in an emulator, fails in an emulator with API 23 with this error "java.lang.ClassCastException: android.database.MatrixCursor cannot be cast to java.lang.Boolean".

Clarified that, lets do this. Having an extension from Context object, that is called, val Context.googleCalendars: List<Pair<Long, String>>, this extension filters calendars witch calendar name doesn't ends with "@google.com", I am testing the correct behavior of this extension with this AndroidTest.

Yes you can download the repo from here.

@Test
    fun getGoogleCalendarsTest() {

        // mocking the context
        val mockedContext: Context = mockk(relaxed = true)

        // mocking the content resolver
        val mockedContentResolver: ContentResolver = mockk(relaxed = true)

        val columns: Array<String> = arrayOf(
            CalendarContract.Calendars._ID,
            CalendarContract.Calendars.NAME
        )

        // response to be stubbed, this will help to stub
        // a response from a query in the mocked ContentResolver
        val matrixCursor: Cursor = MatrixCursor(columns).apply {

            this.addRow(arrayOf(1, "username01@gmail.com"))
            this.addRow(arrayOf(2, "name02")) // this row must be filtered by the extension.
            this.addRow(arrayOf(3, "username02@gmail.com"))
        }

        // stubbing content resolver in the mocked context.
        every { mockedContext.contentResolver } returns mockedContentResolver

        // stubbing the query.
        every { mockedContentResolver.query(CalendarContract.Calendars.CONTENT_URI, any(), any(), any(), any()) } returns matrixCursor

        val result: List<Pair<Long, String>> = mockedContext.googleCalendars

        // since googleCalendars extension returns only the calendar name that ends with @gmail.com
        // one row is filtered from the mocked response of the content resolver.
        assertThat(result.isNotEmpty(), Matchers.`is`(true))
        assertThat(result.size, Matchers.`is`(2))
    }
Related