Robolectric和IntentServices

pba*_*ann 14 android unit-testing broadcastreceiver robolectric intentservice

使用Robolectric,如何测试一个广播意图作为响应的IntentService?

假设以下课程:

class MyService extends IntentService {
    @Override
    protected void onHandleIntent(Intent intent) {
        LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("action"));
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的测试用例中,我试图做这样的事情:

@RunWith(RobolectricTestRunner.class)
public class MyServiceTest{
    @Test
    public void testPurchaseHappyPath() throws Exception {

        Context context = new Activity();

        // register broadcast receiver
        BroadcastReceiver br = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                // test logic to ensure that this is called
            }

        };
        context.registerReceiver(br, new IntentFilter("action"));

        // This doesn't work
        context.startService(new Intent(context, MyService.class));

    }

}
Run Code Online (Sandbox Code Playgroud)

MyService从未使用此方法启动.我对Robolectric比较陌生,所以我可能会遗漏一些明显的东西.在调用startService之前是否需要进行某种绑定?我已经通过在上下文中调用sendBroadcast验证了广播的工作原理.有任何想法吗?

Edw*_*ale 12

您无法像尝试那样测试服务初始化.当你在Robolectric下创建一个新活动时,你得到的活动实际上是一种ShadowActivity(有点).这意味着当你调用时startService,实际执行的方法就是这个,它只是调用ShadowApplication#startService.这是该方法的内容:

@Implementation
@Override
public ComponentName startService(Intent intent) {
    startedServices.add(intent);
    return new ComponentName("some.service.package", "SomeServiceName-FIXME");
}
Run Code Online (Sandbox Code Playgroud)

您会注意到它实际上并没有尝试启动您的服务.它只是说明您尝试启动该服务.这对于某些受测试代码应该启动服务的情况很有用.

如果要测试实际服务,我认为您需要模拟初始化位的服务生命周期.像这样的东西可能会起作用:

@RunWith(RobolectricTestRunner.class)
public class MyServiceTest{
    @Test
    public void testPurchaseHappyPath() throws Exception {

        Intent startIntent = new Intent(Robolectric.application, MyService.class);
        MyService service = new MyService();
        service.onCreate();
        service.onStartCommand(startIntent, 0, 42);

        // TODO: test test test

        service.onDestroy();
    }
}
Run Code Online (Sandbox Code Playgroud)

我不熟悉Robolectric如何对待BroadcastReceivers,所以我把它留了出来.

编辑:在JUnit @Before/ @After方法中进行服务创建/销毁可能更有意义,这将允许您的测试仅包含onStartCommand和"测试测试"位.