问题
I am calling the following code in my app:
Snackbar.make(this, R.string.empty_task_message, Snackbar.LENGTH_LONG)
.show()
How can I assert that this was indeed called, inside my Robolectric test?
I was thinking of something like traversing the view hierarchy and searching for a Snackbar
instance and checking if the view is visible.
This looks like a long standing problem in Robolectric.
回答1:
Use a custom shadow:
see an example in my github reop: https://github.com/cafesilencio/snackbarshadow
val activity = Robolectric.buildActivity(MainActivity::class.java).create().start().resume().visible().get()
activity.doSomethingToTriggerASnackbar()
assertThat(ShadowSnackbar.getTextOfLatestSnackbar(), 'is'(activity.getString(R.string.ok))
回答2:
Rather than creating a ShadowClass
I found a much better (simpler and less hacky) way:
/**
* @return a TextView if a snackbar is shown anywhere in the view hierarchy.
*
* NOTE: calling Snackbar.make() does not create a snackbar. Only calling #show() will create it.
*
* If the textView is not-null you can check its text.
*/
fun View.findSnackbarTextView(): TextView? {
val possibleSnackbarContentLayout = findSnackbarLayout()?.getChildAt(0) as? SnackbarContentLayout
return possibleSnackbarContentLayout
?.getChildAt(0) as? TextView
}
private fun View.findSnackbarLayout(): Snackbar.SnackbarLayout? {
when (this) {
is Snackbar.SnackbarLayout -> return this
!is ViewGroup -> return null
}
// otherwise traverse the children
// the compiler needs an explicit assert that `this` is an instance of ViewGroup
this as ViewGroup
(0 until childCount).forEach { i ->
val possibleSnackbarLayout = getChildAt(i).findSnackbarLayout()
if (possibleSnackbarLayout != null) return possibleSnackbarLayout
}
return null
}
use as:
val textView: TextView? = rootView.findSnackbarTextView()
assertThat(textView, `is`(notNullValue()))
The above code is kotlin, you can implement the same in java
回答3:
Modified Java version of vedant1811s example:
private TextView findSnackbarTextView(View rootView) {
final Snackbar.SnackbarLayout snackbarLayout = findSnackbarLayout(rootView);
return snackbarLayout == null ? null : (TextView) snackbarLayout.getChildAt(0)
.findViewById(android.support.design.R.id.snackbar_text);
}
private Snackbar.SnackbarLayout findSnackbarLayout(View rootView) {
if (rootView instanceof Snackbar.SnackbarLayout) {
return (Snackbar.SnackbarLayout) rootView;
} else if (rootView instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) rootView).getChildCount(); i++) {
if (findSnackbarLayout(((ViewGroup) rootView).getChildAt(i)) != null) {
return findSnackbarLayout(((ViewGroup) rootView).getChildAt(i));
}
}
return null;
} else {
return null;
}
}
来源:https://stackoverflow.com/questions/50841565/robolectric-test-to-check-if-a-snackbar-is-shown