android - 如何在Kotlin Android UI测试中初始化模拟的外部依赖项

标签 android kotlin dependency-injection mockito dagger-2

我将在Kotlin中开发一个Android应用程序,并且试图弄清楚如何初始化模拟的依赖关系。例如,该应用将对服务器进行API调用,从位置提供者获取用户的位置,从内容管理系统中提取图像,将数据本地存储在数据库和Android的“共享的偏好设置”中,并根据当前约会时间。因此,我要模拟很多外部依赖项,包括当前日期/时间,以便我可以验证年龄计算等。

我的测试目标只是使用Android检测的测试来验证我的应用程序的屏幕。我不希望依赖于真正的外部系统,因为测试这些系统是这些系统的开发人员的责任。

在阅读Android的文档Consider whether to use test doubles时,我注意到它提供了一个很好的提示:“提示:请与库作者联系,以查看他们是否提供您可以可靠地依赖的任何官方支持的测试基础结构,例如伪造品。”但是,该文档并没有真正说明如何初始化第三方测试基础结构。

以下是到目前为止我对我的选择的了解,但是所有这些又回到了我不了解的基本知识:被测试的Android应用如何知道它应该以测试模式还是生产模式运行?

  • 模拟,例如Mockito或MockK:模拟似乎是为测试量身定制的依赖项注入(inject)的一种特殊情况。我看到的示例涉及测试类或方法,而不是全面系统。这些示例通常显示如何模拟一个类并将其传递给测试中的类/方法。但是对于全尺寸系统,测试代码可在通过Espresso引用的小部件上运行。无法访问逻辑所在的类。我的印象是模拟是针对单元测试,而不是UI测试。但是也许有人可以解释如何使用模拟进行UI测试:
  • a)假设外部依赖关系在调用堆栈的深处初始化。如果我在测试代码的设置函数中定义了模拟(例如,使用@Before注释的方法),如何将其传递给依赖它的代码中的位置?
  • b)我一直读到模拟在Kotlin中不起作用,因为Kotlin将所有类都定义为final。似乎有一些解决方法。但是Google / Android是否确实推荐其中一种(我在他们的文档中没有阅读过)。
  • 依赖注入(inject),例如Dagger 2:如果模拟不能用于UI测试,那么我应该使用依赖注入(inject)吗?据我了解,Dagger 2似乎通过定义顶级组件和模块树来解决上述问题1.a,它们可以在堆栈的任何层提供依赖关系。为了进行测试,似乎我将提供一个模拟实际依赖关系的不同组件。
  • a)在Android的测试中,在其中实例化设计用于测试的Dagger 2组件。如何确定使用了组件而不是用于生产的组件?
  • 在启动测试之前进行准备:我可以看到如何在启动应用程序之前自定义build.gradle以准备测试环境。例如,我可以将一个标志传递给我的应用程序,以便在调用应用程序的onCreate()时,可以配置系统以通过“依赖注入(inject)”,“模拟”甚至只是自定义实现来准备仿真的依赖项。例如,某些外部依赖项具有测试模式,在该模式下,我需要将标志传递给它们,以便它们在测试模式下工作。我不清楚这种事情如何与“依赖注入(inject)”或“模拟”相吻合,但是我想我可以看到如何将这些机制用作包装器来传递测试标志。在下面的文章中,有人想要模拟一个位置提供程序,然后他们修改了build.gradle文件以在Android测试基础结构启动之前进行设置。
    How to set Allow Mock Location on Android Device before executing AndroidTest with uiautomator and espresso?

  • 总之,我想使用带有Espresso的Android仪器测试来测试Kotlin Android应用程序的UI,但是我不知道如何设置测试,以便外部依赖项使用仿真代码而不是生产代码。我应该使用模拟,依赖注入(inject)还是通过build.gradle自定义?有人可以帮助我使我的想法步入正轨吗?

    最佳答案

    经过大量搜索后,我发现Android ActivityTestRule允许您推迟启动Activity。如Fast Mocked UI Tests on Android Kotlin所示,这使测试代码有时间初始化仿真的依赖项。

    关于android - 如何在Kotlin Android UI测试中初始化模拟的外部依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57011143/

    相关文章:

    kotlin - 在 Mac 上哪里可以找到(安装)Kotlin cinterop 工具

    dependency-injection - 我应该如何为 DI/IOC 订购我的 ctor 参数?

    angularjs - 关于 AngularJS 依赖的困惑

    java - 自动分离mm :ss in editText?

    android - 服务类中的 SharedPreferences 不起作用(空指针)

    suppress-warnings - 在 Kotlin 中标记未使用的参数

    c# - 如何在 Azure Functions 中混合使用自定义参数绑定(bind)和依赖项注入(inject)?

    java - 验证 Android 代码签名

    java - 将textview中的数字转换为int

    kotlin - Kotlin标准函数,如果为null则创建并返回所有结果