使用Robolectric进行Toast消息内容的单元测试

6

我有一个Activity,它什么都不做,只显示一个类似以下的Toast消息。

public MyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Toast.makeText(this, "Some message", Toast.LENGTH_LONG).show();
        finish(); // Finish the activity here. 
    }
}

我想使用Robolectric编写单元测试来验证Toast的内容。我尝试了以下代码:

@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {

    @Before
    public void setup() {
        Robolectric.buildActivity(MyActivity.class).create();
    }

    @Test
    public void testToast() {
        assertTrue(ShadowToast.showedCustomToast("Some message", R.string.some_message));
        assertThat(ShadowToast.getTextOfLatestToast().toString(), equalTo("Some message"));
    }
}

看起来它们都不起作用。有什么想法?

提前感谢!


这个看起来有几个问题: 1)你可以从任何地方发送Toast:为什么要创建一个Activity来做这件事? 2)为什么要测试Android Toast系统?如果它不起作用,你会怎么做? 3)Toast是Binder的薄包装器:它将文本传输到完全不同的应用程序,该应用程序打印消息。这将非常难以模拟。 - G. Blake Meike
你尝试过使用 ShadowToast.showedToast(CharSequence message) 吗? - ahasbini
@ahasbini 是的,我想我也试过那个。谢谢你的评论! - Reaz Murshed
@G.BlakeMeike非常感谢您的评论。我正在尝试在此做出回应。该活动只是提供示例的虚拟对象。我不想测试Android Toast系统,而是要测试Toast的内容并检查是否出现。看起来Robolectric提供了一些Shadow技术,但迄今为止,它们都没有对我起作用。 - Reaz Murshed
2
@ReazMurshed 你可能称它为“Toast”,但它现在不再是“Toast”了(正如Blake解释的那样)。我只能想象通过UiAutomator2可以获得对实际“Toast”的控制(因为它可以访问应用程序范围之外的视图)。 - Martin Zeitler
显示剩余5条评论
1个回答

1

我设法解决了我的问题,并最终使用Robolectric创建了一个自定义布局来显示toast消息并测试toast内容。我在这里添加了一个GitHub项目,其中包含一个可工作的示例。

public class MainActivityTest {

    @Before
    public void setup() {
        Robolectric.buildActivity(MainActivity.class).create();
    }

    @Test
    public void testToastMessage() {
        ToastLayoutBinding binding = DataBindingUtil.getBinding(ShadowToast.getLatestToast().getView());
        binding.executePendingBindings();

        assertEquals(binding.toastMsg.getContext().getString(R.string.some_toast),
                binding.toastMsg.getText());
    }

    @Test
    public void testToastDuration() {
        assertEquals(Toast.LENGTH_LONG, ShadowToast.getLatestToast().getDuration());
    }
}

自定义 Toast 的布局如下所示。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="android.text.TextUtils" />

        <variable
            name="msg"
            type="String" />
    </data>

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="4dp">

        <TextView
            android:id="@+id/toast_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="sans-serif"
            android:gravity="center"
            android:text="@{TextUtils.isEmpty(msg) ? @string/no_msg : msg}" />
    </FrameLayout>
</layout>

而显示 Toast 消息的函数如下所示。

/**
* Display a custom toast with some message provided as a function parameter
*
* @param activity An {@link Activity} where the toast message will be shown
* @param msg      a {@link String} that holds the message to be shown as a Toast
* @throws IllegalArgumentException if a null activity is passed to the function
* @apiNote If a null String is passed as a #msg parameter, then this function shows a default text (no_toast)
*/
public static void showToast(Activity activity, String msg) {

    if (activity == null) {
        throw new IllegalArgumentException("The passed in activity cannot be null");
    }

    if (msg == null) {
        msg = activity.getString(R.string.no_msg);
    }

    ToastLayoutBinding toastLayout = DataBindingUtil.inflate(
            activity.getLayoutInflater(), R.layout.toast_layout, null, false);
    toastLayout.setMsg(msg); // Set the toast message here

    Toast toast = new Toast(activity);
    toast.setView(toastLayout.getRoot());
    toast.setGravity(Gravity.TOP, 0, 200);
    toast.setDuration(Toast.LENGTH_LONG);
    toast.show();
}

我已经使用了数据绑定,但是这也适用于其他布局膨胀方法。

希望这能帮助其他遇到同样问题的开发者。


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