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

2023-11-22

情况

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

“该规则提供了单个活动的功能测试。 被测试的活动将在每个测试之前启动,注释为 @Test 以及任何用 @Before 注释的方法之前。这将是 测试完成后终止,所有方法注释为 @完成后。可以在以下期间访问被测试的活动 通过调用 ActivityTestRule#getActivity() 进行测试。”

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


问题

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

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

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


问题

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

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


证据

如果您想看到这种行为,只需要几分钟。使用这样的活动创建一个新项目:

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

和这样的测试类:

@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,但这没关系。不好的是,由于这种不可预测的顺序,我的测试不稳定。

我知道这可能是故意的,并且可能有一种简单的方法来处理它,我只是没有足够幸运找到它。如果您知道这是什么,请在此处发布答案。我不在乎事后看来我的问题有多愚蠢,我在这个问题上花了很多时间。这几乎总是简单的事情,所以我准备好为答案感到尴尬。


解决方法

使用 onPause 而不是 OnDestroy 会产生副作用,即当我 startActivityForResult 时被调用,但在平板电脑模式下不会在后台片段中再次调用 onResume。我正在探索实现这项工作的方法,但尚未找到解决方案。

Edit:onPause 最终遇到了同样的问题 - 这就是我首先使用 onDetach 的部分原因。最终,有时我不想分离监听器,直到片段被销毁。

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


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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 如何为android数据绑定点击监听器编写proguard规则?

    我在用databinding在我的应用程序中 它运行良好 但是当我启用minifyEnabled true and shrinkResources true比它告诉我一些错误 Execution failed for task app tr
  • 如何通过代码检测Android上的表情符号支持

    通过代码 我可以制作一个按钮 将这 3 个表情符号插入到文本中 不过 在许多手机上 当用户单击按钮时 问题是 显示为 X X X 或者更糟糕的是 它只显示三个空白空间 我想在无法正确显示表情符号的 Android 设备上禁用并隐藏我自己的内
  • Android Widget ID 是否持久

    在从桌面删除该 Widget 实例之前 您从操作系统收到的用户桌面上特定 Widget 实例的 Widget ID 是否一致 我找不到任何明确说明这一点的文档 但我假设这是因为文档说您可以使用小部件 id 来存储任何实例配置信息 我想将一些
  • 如何从Slog中查看日志

    如何查看 Slog API 生成的日志 是否有任何选项可以查看系统缓冲区中的日志 我的意思是查看我们使用的无线电缓冲区的日志 adb logcat b 无线电 而这个日志是由Android的Log类生成的 Slog API 的输出在哪里 怎
  • 突出显示列表视图项目

    我需要在触摸列表视图项目时突出显示它并保持突出显示状态 我尝试了我发现的一切 但没有任何效果 这是我的代码 这是列表视图
  • 将项目添加到 android 框架的设置中

    我正在 android 框架中工作 我想向 android 操作系统中的现有设置添加一个项目 您能告诉我如何执行此操作吗 首先阅读有关偏好活动 http developer android com reference android pre
  • 如何最大限度地减少 Google API(地点)自动完成的请求量?

    我正在使用 google API 位置来自动完成位置AutoCompleteTextView 我做了几次测试 大概进行了 20 次搜索 在我的 google devs 个人资料中 写着我已经发出了 200 个 API 请求 据我所知 每次我
  • 使用 RoboSpice 有没有办法从异常中获取 HTTP 错误代码?

    我正在编写一个使用 RoboSpice 的应用程序 在请求侦听器 onRequestFailure SpiceException arg0 中 有没有办法确定该错误是由于发生 401 HTTP 错误而导致的 我有一个后端服务 当令牌过期时
  • Android 游戏偶尔出现延迟

    我正在用 Java 制作一个简单的 Android 游戏 我注意到每 20 40 秒就会出现一些烦人的延迟 首先 我认为它们是由垃圾收集器引起的 但当我检查 LogCat 时 我发现游戏滞后时没有垃圾收集 每当游戏开始滞后时 我都会标记日志
  • 使用 START_STICKY 启动时服务进程被终止后的 onStartCommand

    我一直在阅读 Android 文档 我想知道是否有人可以阐明当以 START STICKY 启动的服务的进程被终止时服务实例会发生什么情况 我假设本地状态数据 实例变量 也丢失了 Android 在重新创建服务时是否会采取任何措施来帮助重新
  • 在 Android 中使用 AES 加密的最佳实践是什么?

    我为什么问这个问题 我知道人们对 AES 加密存在很多疑问 即使对于 Android 也是如此 如果您在网络上搜索 会发现很多代码片段 但在每个页面上 在每个 Stack Overflow 问题中 我都发现了另一个具有重大差异的实现 所以我
  • 旋转 Google 地图中的两层标记图标

    在我的应用程序中 我向地图添加了一定数量的标记 如下所示 private fun addMarker googleMap GoogleMap location Location val options MarkerOptions optio
  • 何时调用 glMatrixMode()

    我所关注的大多数 Android OpenGL ES 教程都有其 onSurfaceChanged 函数 如下所示 public void onSurfaceChanged GL10 gl int width int height gl g
  • 片段活动中的 commitAllowingStateLoss()

    我的应用程序使用片段活动 它仅处于纵向模式 无法旋转屏幕 最初我使用的是commit 方法 但现在我计划不加区别地将这些更改为commitAllowingStateLoss 对于碎片活动 是否有任何理由不不加区别地执行此操作而不重新评估我使
  • Fresco:滚动 RecyclerView 后图像消失

    我有一个 Horizo ntal RecyclerView 每个项目都有一个使用 Facebook Fresco 图像库加载到其中的图像 然而 虽然正确的图像最初是在屏幕上滚动一点时加载的 但当 RecyclerView 进一步滚动时 它就
  • 如何让surfaceview透明

    大家好 我想让我的 DrawingSurface 视图透明 我尝试了很多东西 但它不起作用 这是我的 xml 代码 使我的表面视图透明
  • Android:选择 EditField 上焦点上的所有文本

    我试图让 Android 在获得焦点时选择 EditText 字段中的所有文本 我在布局中使用此属性 在两个字段上 android selectAllOnFocus true 我不确定这是否相关 但为了将光标移动到第一个可编辑字段 前面 还
  • 片段中的 SavedInstanceState 始终为 null

    我使用 XML 以及活动中的 setContentView 将片段附加到活动 A 有一个问题 因为我的片段中有非常动态的视图 所以当方向改变时 我必须恢复所有的观点状态 我有问题 因为我正在使用类似的东西 public void onSav
  • 将主题应用到 v7 支持操作栏

    我正在使用support v7库来实现ActionBar在我的应用程序中 我的styles xml file
  • Android Webview隐私浏览

    我在我的 Android 应用程序中使用 webview 从多个站点获取一些网页 我对 webview 行为有一些疑问 webview 是否存储历史记录 cookie 表单自动填充信息 如果是的话 我们可以阻止它这样做吗 如果 Webvie

随机推荐