Robolectric test to check if a SnackBar is shown?

醉酒当歌 提交于 2019-12-25 01:49:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!