Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test on Kotlin Extension Function on Android SDK Classes

Kotlin extension function is great. But how could I perform unit test on them? Especially those that is of Android SDK provided class (e.g. Context, Dialog).

I provide two examples below, and if anyone could share how I could unit test them, or if I need to write them differently if I really want to unit test them.

fun Context.getColorById(colorId: Int): Int {
    if (Build.VERSION.SDK_INT >= 23)
        return ContextCompat.getColor(this, colorId)
    else return resources.getColor(colorId)
}

and

fun Dialog.setupErrorDialog(body : String, onOkFunc: () -> Unit = {}): Dialog {
    window.requestFeature(Window.FEATURE_NO_TITLE)
    this.setContentView(R.layout.dialog_error_layout)

    (findViewById(R.id.txt_body) as TextView).text = body
    (findViewById(R.id.txt_header) as TextView).text = context.getString(R.string.dialog_title_error)
    (findViewById(R.id.txt_okay)).setOnClickListener{
        onOkFunc()
        dismiss()
    }
    return this
}

Any suggestion would help. Thanks!

like image 220
Elye Avatar asked Aug 08 '16 02:08

Elye


1 Answers

The way I'm testing extension functions on Android classes at the moment is by mocking the Android class. I know, this is not an optimal solution as it mocks the class under test and requires certain knowledge about how the function works (as it is always the case when mocking), but as extension functions are internally implemented as static functions I guess it's acceptable until someone comes up with something better.

As an example consider the JsonArray class. We've defined an extension function for receiving the last item's index:

fun JSONArray.lastIndex() = length() - 1

The according test (using the Spek test framework and mockito-kotlin) looks like this.

@RunWith(JUnitPlatform::class)
object JsonExtensionTestSpec : Spek({

    given("a JSON array with three entries") {
        val jsonArray = mock<JSONArray> {
            on { length() } doReturn 3
        }

        on("getting the index of the last item") {
            val lastIndex = jsonArray.lastIndex()

            it("should be 2") {
                lastIndex shouldBe 2
            }
        }
    }

    given("a JSON array with no entries") {
        val jsonArray = mock<JSONArray>({
            on { length() } doReturn 0
        })

        on("getting the index of the last item") {
            val lastIndex = jsonArray.lastIndex()

            it("should be -1") {
                lastIndex shouldBe -1
            }
        }
    }
})

The difficulty with your functions is, that they also use Android classes internally. Unfortunately I don't have a solution for this right now.

like image 191
ubuntudroid Avatar answered Nov 12 '22 16:11

ubuntudroid