Call view methods when testing by Espresso and Kotlin in Android

A. A.
AndroidPub
Published in
2 min readOct 9, 2018

When you write UI test with espresso it's common when you need to call a method on a testing view, and it’s very easy, all you have to do is define a new View Action like below:

onView(withId(R.id.myView))
.perform(object: ViewAction {
override fun getDescription(): String {
return "call doSomething() method"
}

override fun getConstraints(): Matcher<View> {
return isEnabled()
}

override fun perform(uiController: UiController?, view: View?) {
(view as MyCustomView).doSomething()
}
})

This method has two problems, first, it makes the code ugly! and second, you have to define this for every single method!

I’m here to tell you that there is a much better way that solves both these issues, the calling code would be like this and it works on any view even custom views.

onView(withId(R.id.myView))
.perform(callMethod<MyCustomView> {
it
.doSomething()
})

To make this code work all you have to do is to define a generic function that returns a ViewAction like below:

private fun <T>callMethod(message: String = "", someMethod: (view: T) -> Unit): ViewAction {
return object: ViewAction {
override fun getDescription(): String {
return if(message.isBlank()) someMethod.toString() else message
}

override fun getConstraints(): Matcher<View> {
return isEnabled()
}

override fun perform(uiController: UiController?, view: View?) {
someMethod(view!! as T)
}
}
}

This function uses generic types so it can use the type to cast the view so when you’re testing you don’t have to cast the view yourself, you simply call the methods on the view.

Second, it uses a cool feature of Kotlin that allows you to pass a function as a parameter to another function, and in perform section it simply calls that function, so you can pass any function to this method and it simply runs it for you!

Note: When this method fails for any reason the error message is not very intuitive by default, its something like this:

Error performing ‘Function1<mypackagename.component.MyCustomView, kotlin.Unit>’ on view ‘with id: mypackagename:id/myView’.

I don’t usually care about this because even without the error message it gives me enough data to debug the issue but if you want a better message you can use this ViewAction like this:

onView(withId(R.id.myView))
.perform(callMethod<MyCustomView>("call doSomething() method") {
it
.doSomething()
})

That turns the error to be like this:

Error performing call doSomething() method on view ‘with id: mypackagename:id/myView’.

I hope this helps you write cleaner code for testing, Let me know what you think in the comments section below.

--

--