Unit Testing Methods That Use Cursors

Unit testing methods that use a Cursor can be difficult because typically the cursor comes from a query on a database. Creating a database for a unit test is too heavy, and allowing a unit test to have access to a database for testing breaks the principle that unit tests should be testing only the method under test.

We’re going to cover an easy way to create a cursor with data for testing using a MatrixCursor.

First, let’s look at the method we want to test:

Method under testThe method simply looks to see if the cursor is sorted by the “name” column or not. If the cursor is null, or if it contains less than two rows, then it is considered to be sorted. Otherwise, String.compareTo() is used to determine if the rows are in order.

In our test class, there are two basic cases that we want to cover: if the cursor is sorted and if it isn’t.

Test methodsIgnore line 10 for now. Line 11 defines an alphabetized array of Strings and line 12 defines an unalphabetized array of Strings. The first method, test_isSortedByName_inOrder() creates a cursor using the alphabetized array, and then asserts that the output of isSortedByName() is true.

Conversely, the second method, test_isSortedByName_outOfOrder() creates a cursor using the unalphabetized array, and then asserts that the output of isSortedByName() is false.

Now, the only thing left to do is write setupMatrixCursor(). This is where we want to avoid creating and using a real database. To do this, we’ll use a MatrixCursor:

Setup methodOn line 27, we create the names of the columns. The thing that is important is that we have a column with the name that our method under test is expecting and that all of the column names are unique. The order of the columns doesn’t matter. On line 28, we create the MatrixCursor using those column names.

On line 29, we create a RowBuilder. RowBuilder is a convenience class which makes the code to fill a MatrixCursor with data a bit cleaner. The builder allows us to add the row elements one at a time. The other option is to use MatrixCursor.addRow(), which takes an array of all of the objects in the row at once.

Next, we’re going to fill the cursor with data. The “dummy” columns will be filled with any arbitrary data we want and the “name” column will be filled using the String array that was passed in. On line 31, we’re doing a quick assert to ensure that the arrays of “dummy” and “name” data are the same length (otherwise, we risk an ArrayIndexOutOfBoundsException, or not using all of the data that was passed in). This assert isn’t testing our code, rather it’s ensuring that when new test cases get written, that they are written correctly.

On line 33, we get our builder for the new row, and then on lines 34-37, we fill the builder with our data. The order here needs to be in the same order as the column names on line 27.

Finally, once we’ve added all of the data we want, we can return the cursor. And that’s all there is to it.

A couple of notes on this code. In a real test class, I would want to test all possible permutations of inputs to my method. We omitted the null case, the empty cursor case, and the cursor with only one row case. One other possibility is that our cursor doesn’t contain a “name” column; that would be a testable case as well.

If you’d like the source, you can download it from here.