如何使用 Robolectric 测试 IntentService?

2024-01-08

我正在尝试测试onHandleIntent()的方法IntentService using Robolectric.

我正在启动该服务:

Activity activity = new Activity();
Intent intent = new Intent(activity, MyService.class);
activity.startService(intent);

ShadowActivity shadowActivity = Robolectric.shadowOf(activity);
Intent startedIntent = shadowActivity.getNextStartedService();
assertNotNull(startedIntent);

似乎startedIntent不为空,但是onHandleIntent()似乎没有被调用。

我应该如何测试它?


Robolectric 有一个ServiceController https://github.com/robolectric/robolectric/blob/robolectric-3.0/robolectric/src/main/java/org/robolectric/util/ServiceController.java它可以像活动一样贯穿服务生命周期。该控制器提供了执行相应服务回调的所有方法(例如controller.attach().create().startCommand(0, 0).destroy()).

理论上我们可以预期IntentService.onStartCommand() https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/IntentService.java#130将触发IntentService.onHandleIntent(Intent),通过其内部Handler。然而这Handler uses a Looper它在后台线程上运行,我不知道如何使该线程前进到下一个任务。解决方法是创建TestService模仿相同的行为,但触发onHandleIntent(Intent)在主线程上(用于运行测试的线程)。

@RunWith(RobolectricGradleTestRunner.class)
public class MyIntentServiceTest {
    private TestService service;
    private ServiceController<TestService> controller;

    @Before
    public void setUp() {
        controller = Robolectric.buildService(TestService.class);
        service = controller.attach().create().get();
    }

    @Test
    public void testWithIntent() {
        Intent intent = new Intent(RuntimeEnvironment.application, TestService.class);
        // add extras to intent
        controller.withIntent(intent).startCommand(0, 0);
        // assert here
    }

    @After
    public void tearDown() {
        controller.destroy();
    }

    public static class TestService extends MyIntentService {
        public boolean enabled = true;

        @Override
        public void onStart(Intent intent, int startId) {
            // same logic as in internal ServiceHandler.handleMessage()
            // but runs on same thread as Service
            onHandleIntent(intent);
            stopSelf(startId);
        }
    }
}

UPDATE:或者,为 IntentService 创建类似的控制器也非常简单,如下所示:

public class IntentServiceController<T extends IntentService> extends ServiceController<T> {
    public static <T extends IntentService> IntentServiceController<T> buildIntentService(Class<T> serviceClass) {
        try {
            return new IntentServiceController<>(Robolectric.getShadowsAdapter(), serviceClass);
        } catch (IllegalAccessException | InstantiationException e) {
            throw new RuntimeException(e);
        }
    }

    private IntentServiceController(ShadowsAdapter shadowsAdapter, Class<T> serviceClass) throws IllegalAccessException, InstantiationException {
        super(shadowsAdapter, serviceClass);
    }

    @Override
    public IntentServiceController<T> withIntent(Intent intent) {
        super.withIntent(intent);
        return this;
    }

    @Override
    public IntentServiceController<T> attach() {
        super.attach();
        return this;
    }

    @Override
    public IntentServiceController<T> bind() {
        super.bind();
        return this;
    }

    @Override
    public IntentServiceController<T> create() {
        super.create();
        return this;
    }

    @Override
    public IntentServiceController<T> destroy() {
        super.destroy();
        return this;
    }

    @Override
    public IntentServiceController<T> rebind() {
        super.rebind();
        return this;
    }

    @Override
    public IntentServiceController<T> startCommand(int flags, int startId) {
        super.startCommand(flags, startId);
        return this;
    }

    @Override
    public IntentServiceController<T> unbind() {
        super.unbind();
        return this;
    }

    public IntentServiceController<T> handleIntent() {
        invokeWhilePaused("onHandleIntent", getIntent());
        return this;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Robolectric 测试 IntentService? 的相关文章

  • Android - 保存动态更改布局的状态

    我有一个布局 用户可以在其中添加按钮并将其放置在他们想要的位置 我想允许用户保存他们的布局 以便下次打开应用程序时加载它 有谁知道我是否可以将文件保存到 SD 卡上 或者 我可以使用某种layout getXml 方法并将其放入我的应用程序
  • 在应用程序简历中隐藏软键盘

    我有一个 Android 应用程序 使用 Xamarin 用 C 编写 我已将应用程序简化为包含 TextView 和用于横幅广告的 Google admod AdView 的 LinearLayout 我不希望软键盘出现在应用程序中 这不
  • getItem 与 getItemAtPosition

    有两种方法可以获取列表视图中的选定项目 list getAdapter getItem position list getItemAtPosition position 我的问题是 哪一种是首选的做法 我见过人们同时使用这两种方法 您可以使
  • 使用 Android 前台服务为 MediaPlayer 创建通知

    问题就在这里 我目前正在开发一个应用程序 该应用程序必须提供 A 广播播放器 来自 URL 的 AAC 直播 还有一个播客播放器 来自 URL 的 MP3 流 该应用程序必须能够在后台运行 Android 服务 并通过以下方式向用户公开持续
  • 检测到设备正在振动?

    我使用下面的代码来振动设备 public void vibrator try Vibrator vibrator Vibrator getSystemService Context VIBRATOR SERVICE vibrator vib
  • 菜单未显示在应用程序中

    由于某种原因 我的操作菜单在我的 Android Studio 应用程序中消失了 我正在按照教程学习如何创建 Android 应用程序 但最终遇到了这个问题 我正在使用 atm 的教程 http www raywenderlich com
  • KitKat(及更低版本)设备上的 Android Material Design

    我将在我们学校开发一个 Android 应用程序作为一个项目 我想使用 Google 的新 Material Design 但我知道它仅适用于 Android L 设备 Jack Underwood 最近发布了名为 Today Calend
  • 无法在自定义 AOSP 上安装 Google Play 中的某些应用程序:项目不可用。理由:9

    我在尝试从 Google Play 安装某些应用程序时收到以下错误 LibraryUtils isAvailable not available restriction 9 DocUtils getAvailabilityRestricti
  • Android Studio 在编译时未检测到支持库

    由于 Android Studio 将成为 Android 开发的默认 IDE 因此我决定将现有项目迁移到 Android studio 中 项目结构似乎不同 我的项目中的文件夹层次结构如下 Complete Project gt idea
  • 在意图过滤器中使用多个操作时的默认值

    尝试理解 Android 中的意图和操作并查看文档 http developer android com guide topics intents intents filters html 但我一直看到的一件事是定义了多个操作的意图过滤器
  • TextView 之间有分隔线

    我正在尝试在 android studio 中创建以下布局 因为我对 android 东西还很陌生 所以我第一次尝试使用 LinearLayout 并认为这可能无法实现 现在我正在尝试使用RelativeLayout 我已经用颜色创建了这个
  • 带有自定义阵列适配器的微调器不允许选择项目

    我使用自定义阵列适配器作为微调器 但是 当在下拉列表中选择一个项目时 下拉列表保留在那里 并且微调器不会更新 这是错误行为 与使用带有字符串的通用数组适配器相比 这是自定义类 我错过了什么吗 谢谢 public class Calendar
  • Android 启动器快捷方式

    我制作了一个简单的打卡 打卡时钟应用程序 我想向用户添加在主屏幕上创建快捷方式的选项 该快捷方式将切换应用程序的状态 超时 超时 但我根本不希望此快捷方式在屏幕上打开应用程序 这是我的 setupShortcut private void
  • ROOM迁移过程中如何处理索引信息

    CODE Entity tableName UserRepo indices Index value id unique true public class GitHubRepo PrimaryKey autoGenerate true p
  • 材质设计图标颜色

    应该是哪种颜色 暗 材质图标 在官方文档上 https www google com design spec style icons html icons system icons https www google com design s
  • 如何将设备连接到Eclipse?

    我无法解决这个简单的问题 我正在尝试通过 USB 电缆将我的设备连接到 Eclipse 在我的 PC 上 我已经安装了 Eclipse 和 Android SDK 并且在模拟器上运行该程序运行良好 我已在我的电脑上下载并安装了 Samsun
  • Android中webview的截图方法

    我在 webview 中的 html5 canvas 上画了一些线 并尝试使用下面的代码截取 webview 的屏幕截图 WebView webView WebView findViewById R id webview webView s
  • Android:有没有办法以毫安为单位获取设备的电池容量?

    我想获取设备的电池容量来进行一些电池消耗计算 是否可以以某种方式获取它 例如 三星 Galaxy Note 2 的电池容量为 3100mAh 谢谢你的帮助 知道了 在 SDK 中无法直接找到任何内容 但可以使用反射来完成 这是工作代码 pu
  • Android 如何聚焦当前位置

    您好 我有一个 Android 应用程序 可以在谷歌地图上找到您的位置 但是当我启动该应用程序时 它从非洲开始 而不是在我当前的城市 国家 位置等 我已经在developer android com上检查了信息与位置问题有关 但问题仍然存在
  • android Accessibility-service 突然停止触发事件

    我有一个 AccessibilityService 工作正常 但由于开发过程中的某些原因它停止工作 我似乎找不到这个原因 请看一下我的代码并告诉我为什么它不起作用 public class MyServicee extends Access

随机推荐

  • 如何在R中查找列的平均值[重复]

    这个问题在这里已经有答案了 这是我正在使用的 csv 文件 my xldataset lt read csv http www math smith edu sasr datasets help csv 这是我尝试查找 mcs1 列的平均值
  • 在 Varnish 正则表达式中提取捕获组内容

    我在 Varnish 配置语言中有以下正则表达式 abc a zA Z0 9 0 9 现在 我想获取值 2部分 即 0 9 Varnish 中的正则表达式 我怎样才能得到这个值 您可以使用regsub在这种情况下 set req url r
  • 我的视图模型值类型属性应该可以为空吗?

    我已经让我的视图模型属性可以为空已经有一段时间了 我的理由是 当进行验证时 我不希望将默认值插入到用户留空的字段中 但这是必需的 当然 我将必填字段标记为必填 但这让我认为这样做会失去对象模型的大量保真度 当然 我的域类只有在实际上可以为空
  • 如何设置 VS Code 项目以构建 LLVM

    我想使用 VS Code 来构建和调试 LLVM 源代码 有没有一个好的文档解释如何在 VS Code 中为 LLVM 设置项目 提前致谢 我发现以下博客很有用 https developers redhat com blog 2021 0
  • 在 ASP.NET Core 中到达控制器之前拦截不良请求

    如果收到的请求是 BadRequest 我有一个应用逻辑 为此我创建了一个过滤器 public class ValidateModelAttribute ActionFilterAttribute public override void
  • 在前端JS中将ajax请求从一个容器发送到另一个容器

    我为 API 和前端使用不同的 Docker 容器 frontend image
  • 如何使用coldfusion获取href值?

  • 在 Windows 上配置 MongoDB

    我正在尝试在 Windows 上设置 MongoDB 但在线文档似乎不太准确 在 配置 Windows 服务 部分下 step 1 http docs mongodb org manual tutorial install mongodb
  • 使用 jQuery 预加载图像

    我正在寻找一种快速 简单的方法来使用 JavaScript 预加载图像 如果这很重要的话我会使用 jQuery 我在这里看到了这个 http nettuts com http nettuts com tutorials javascript
  • 使用 iOS SDK 将视频发布到 Facebook 时出错

    我有一个应用程序 可以使用适用于 iOS 的 Facebook SDK 将本机 MOV 文件 视频发布到 Facebook 它一直运行没有问题 直到几周前它开始失败并出现以下错误 error code 352 message 352 Sor
  • 在亚马逊 lambda python 中运行 selenium webdriver

    我想在amazon lambda中运行BeautifulSoup和selenium webdriver 我的运行环境是python 3 6 可以跑吗 如果是这样怎么办 我的目的是使用 beautiful soup 4 和 selenium
  • AVAudioRecorder 仅录制中断后的音频

    在我使用 AVAudioRecorder 和 AVAudioPlayer 录制和播放音频的应用程序中 我遇到了来电情况下的场景 当录音正在进行时 如果电话来电 则仅录制电话通话后录制的音频 我希望通话后录制的录音是通话前录制的音频的延续 我
  • Angular 2递归http.gets深度未知

    我一直在使用如下所示的模式将 Angular2 中的 http gets 链接在一起 以从两层深的文件夹 所有伪打字稿 的分层结构中检索信息 myObservable this myService getSubFolders topFold
  • 我的第一个 C# WPF ValidationRule 未触发

    我正在尝试学习如何实现数据验证 但我的第一次尝试不是触发 lblSource Error 事件 有谁知道我错过了什么 我的窗口的 XAML
  • 将 df.apply() 的输出一次写入多个列

    我正在尝试编写一个函数的结果 该函数将多个参数返回到多个 Pandas 列 最初 我使用了 zip df apply 但这感觉非常 hacky 且非Pythonic 我发现 df apply 有一个参数 result type expand
  • php ltrim 一次删除多个字符

    您好 有没有更好更快的方法来清除字符串开头的许多字符 我有这个 但这真的是最快的方法吗 description new ltrim description new description new ltrim description new
  • Pandas:同名列的平均值

    我有一个数据框 其中包含以下列 id name foo1 foo1 foo1 foo2 foo2 foo3 我想要一个新的数据框 其中共享相同名称的列被平均 id name foo1 foo2 foo3 这里 列 foo1 将是原始数据框中
  • 现代 C++ 是否变得更加流行? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何通过 JQuery 提交表单时点击提交按钮

    我有一个带有 2 个提交按钮的表单
  • 如何使用 Robolectric 测试 IntentService?

    我正在尝试测试onHandleIntent 的方法IntentService using Robolectric 我正在启动该服务 Activity activity new Activity Intent intent new Inten