如果添加第二个测试,Espresso toast 测试将失败

Espresso toast test fails if second test is added

我有一个 activity 可以根据从网络服务调用返回的状态显示不同的 toast。

我正在编写一个测试 class,我的第一个测试测试在出现网络错误时会显示其中一个 toast。下面是测试 class:

@RunWith(AndroidJUnit4.class)
public class LoginActivityTest extends BaseTest {

    @Rule
    public final ActivityTestRule<LoginActivity> login = new ActivityTestRule(LoginActivity.class, true);

    @Test
    public void noNetwork() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                login.getActivity().onEventMainThread(new LoginResp(CopiaWebServiceClient.ResponseStatus.NETWORK_ERROR));
            }
        });

        onView(withText(R.string.toast_no_network_connection))
            .inRoot(withDecorView(not(is(login.getActivity().getWindow().getDecorView()))))
            .check(matches(isDisplayed()));
    }
}

所以 noNetwork 测试调用 LoginActivityonEventMainThread(LoginResp loginResp) 方法(这需要 运行 在 UI 线程上,因此我使用 runOnMainSync) 带有网络错误状态以提示它显示预期的 toast_no_network_connection toast。

此测试有效 运行 并成功通过。

这是我的问题:

如果我向测试 class 添加第二个测试,则第二个测试失败。这是第二个测试,与第一个相同,只是它向 onEventMainThread(LoginResp loginResp) 传递了不同的错误状态,因此将显示不同的 toast:

    @Test
    public void serverErr() {
       InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                login.getActivity().onEventMainThread(new LoginResp(CopiaWebServiceClient.ResponseStatus.HTTP_SERVER_ERROR));
            }
        });

        onView(withText(R.string.toast_operation_failure_app_error))
            .inRoot(withDecorView(not(is(login.getActivity().getWindow().getDecorView()))))
            .check(matches(isDisplayed()));
    }

第二次测试失败,输出:android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with string from resource id: <2131689669>[toast_operation_failure_app_error] value: Sorry, failure to complete operation due to application error.

但是,在 运行 进行测试时观察模拟器,我看到了初始的 toast_no_network_connection toast(第一个测试所期望的),然后是 toast_operation_failure_app_error toast(第一个测试所期望的)第二次测试)。为什么第二次测试失败?

跟测试运行ning一个接一个有关系,因为我把第一个测试注释掉了,第二个测试通过了

我在 LoginActivity 中的 onEventMainThread(LoginResp loginResp) 方法具有以下代码,可根据状态显示适当的 Toast:

switch (status) {

        case HTTP_UNAUTHORIZED:
            DialogCreator.createAlertDialog(this, getString(R.string.dialog_msg_login_fail)).show();

            break;

        case NETWORK_ERROR:
            Toast.makeText(this, getString(R.string.toast_no_network_connection), Toast.LENGTH_SHORT).show();

            break;

        default:
            Toast.makeText(this, getString(R.string.toast_operation_failure_app_error), Toast.LENGTH_SHORT).show();

    }

调试测试我看到第一个测试进入 NETWORK_ERROR 案例,正如预期的那样,第二个测试进入 switch 语句的 default 部分,也符合预期。

在进一步测试之后,我选择了 Eirik W 在

的回答中建议的方法

我稍微更改了生产代码,将 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) 注释的 Toast 成员添加到 LoginActivity 以启用 LoginActivityTest 中的 @After 注释方法取消每次测试后显示的任何 toast。