Robolectric测试:如何检查SnackBar是否显示?

3
我在我的应用中调用了以下代码:

我在我的应用中调用了以下代码:

Snackbar.make(this, R.string.empty_task_message, Snackbar.LENGTH_LONG)
    .show()

在我的Robolectric测试中,我如何确定确实被调用了?

我在考虑遍历视图层次结构并搜索Snackbar实例,然后检查该视图是否可见。

这看起来是Robolectric中长期存在的问题。

4个回答

4

我发现一种更好的方法,不需要创建一个ShadowClass(阴影类):

/**
 * @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
}

用途:

val textView: TextView? = rootView.findSnackbarTextView()
assertThat(textView, `is`(notNullValue()))

以上代码是Kotlin编写的,您可以在Java中实现相同的功能。

1
这非常有帮助。非常干净,很 Kotlin 风格。 - ylinkz
你救了我的命! - acmpo6ou

1

使用自定义阴影:

在我的 Github 存储库中查看示例: 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))

0

修改后的Java版本,基于vedant1811s的示例:

    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;
        }
    }

注意:我遇到了时间问题,有时测试找不到小吃店。还没有调查完... - Alix

0

这是我做的方式,遵循了@vedant答案的一般思路:

assertEquals(resources.getString(R.string.empty_task_message),
            rootView.findViewById<TextView>(com.google.android.material.R.id.snackbar_text).text.toString())

这将适用于最新版本的Material Design库。 还需要访问根视图,以搜索Snackbar的TextView。有了根视图,您就可以获得字符串资源的上下文。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接