Espresso 不会等到 Activity 被销毁,然后再为下一次测试创建一个新的

Espresso not waiting till Activity is destroyed, before creating a new one for the next test

情况

在此处的官方文档中:https://google.github.io/android-testing-support-library/docs/rules/index.html,它说:

"This rule provides functional testing of a single activity. The activity under test will be launched before each test annotated with @Test and before any method annotated with @Before. It will be terminated after the test is completed and all methods annotated with @After are finished. The Activity under Test can be accessed during your test by calling ActivityTestRule#getActivity()."

从技术上讲是的,Activity 正在终止。 但似乎无法保证何时会发生这种情况。例如。它不一定会在为下一次测试再次创建之前发生。


问题

在我的一些测试中,我需要依赖在每次测试之后、下一次测试开始之前调用的片段 OnDestroy 或 OnDetach。我有需要清除和重新创建的侦听器。

如果在当前测试的 OnResume 之后调用上一个测试的 onDestroy,则回调被清除,视图不会更新,测试失败。

如果上一个测试的 onDestroy 根本没有被调用,那么当前测试的回调将指向错误的实例。同样,视图将不会更新并且测试将失败。


问题

  1. 在这种情况下讨论这种行为是设计的还是一个错误?我目前无法在文档中找到它。
  2. 处理此问题的最佳做法是什么?我怀疑其他人也遇到过这个问题。

编辑:我现在已经解决了第 2 部分。请参阅下面的解决方法部分。但是,如果有人可以通过引用官方资源来回答第一部分,那么我很乐意接受这个答案。这就是我真正要问的。如果有人有一些想法,第二部分只是一个奖励。


证明

如果您希望看到此行为,只需几分钟。创建一个带有 Activity 的新项目,如下所示:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

和这样的测试 class:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class EspressoLifecycleTest {

    @Rule
    public ActivityTestRule<MainActivity> mActivityRule =
        new ActivityTestRule<>(MainActivity.class);

    @Test
    public void test1() {
    }

    @Test
    public void test2() {
    }

    @Test
    public void test3() {
    }

    @Test
    public void test4() {
    }
}

在 OnResume 和 OnDestroy 方法上放置断点,运行测试套件处于调试模式。

这样做几次,注意 Activity 生命周期方法的调用顺序不一致。例如。它可能会连续调用两次 OnResume,然后调用一次 OnDestroy,然后再次调用 OnResume 两次,然后调用 OnDestroy 三次,或者您可以想到的任何其他组合。当然,它总是以至少一个 OnResume 开始。有时,如果它在最后,它甚至不会调用 OnDestroy,但这没关系。不好的是,由于这种不可预测的顺序,我的测试不稳定。

我知道这可能是故意的,可能有一个简单的方法来处理它,我只是没有足够幸运地找到它。如果你知道它是什么,请 post 在这里回答。我不在乎事后看来我的问题有多愚蠢,我在这个问题上花了很多时间。这几乎总是一些简单的事情,所以我准备好被答案弄得尴尬。


解决方法

在 OnDestroy 上使用 onPause 有一个副作用,即在我启动 ActivityForResult 时被调用,但在平板电脑模式下不会在后台片段中再次调用 onResume。我正在探索使这项工作可行的方法,但目前还没有解决方案。

编辑: onPause 最终遇到了同样的问题——这部分是我首先使用 onDetach 的部分原因。最终,有时我不想在片段被销毁之前分离侦听器。

这让我想到了下一个可行的想法!万岁! 到目前为止,我一直在为调用 Activity 创建回调,因为它要求的是 only 如果那个特定的回调不存在。事实证明这是个坏主意。我这样做是为了将回调的数量限制为所需的确切数量。动机很好,但实施需要所有这些回调清除。解决方案是在从片段调用时重新创建每个回调。如果它为 null,则不要创建它,总是 创建它并替换之前的任何内容。现在根本不需要清除它们 (AFAIK)。

之前注意到这个问题,'solution'我能想到的是覆盖 ActivityTestRule 中的方法:afterActivityFinished()beforeActivityLaunched()。基本上你想检查并等待听众在下一次测试执行之前被清除。

IMO,这是 ActivityTestRule 的错误。

这是一个错误:http://b.android.com/201513

我使用 fork 解决它:https://github.com/shazam/fork