16

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!

Elye
  • 53,639
  • 54
  • 212
  • 474
  • 1
    Hi, I don't think that you need to unit-test these functions. First, gets color from android resources and not depends on yours application code. The second one shows errorDialog, why don't you use Espresso or Robotium or another UI test framework to check if it's properly displayed? – piotrek1543 Aug 15 '16 at 10:03
  • 1
    Thanks piotrek. The code is just for example. The main gist of the question is to explore how can unit test be done on the Extension function, in the event if there's some logic within that is needed to be tested. Is this something un-achievable, or I miss out something? Thanks. – Elye Aug 15 '16 at 13:06
  • I am looking for it as well. Have you found it @Elye ? – elsennov Jan 04 '17 at 15:51
  • http://stackoverflow.com/questions/42379450/how-should-i-test-kotlin-extension-functions – phnmnn Mar 02 '17 at 15:04

1 Answers1

2

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.

ubuntudroid
  • 3,680
  • 6
  • 36
  • 60