简体   繁体   English

如何JUnit测试IntentService

[英]how to JUnit test IntentService

I'm new into Android testing, I want to test an IntentService and I'm currently extending ServiceTestCase. 我是Android测试的新手,我想测试一个IntentService,我现在正在扩展ServiceTestCase。

I'm trying to use a ResultReceiver but the problem is that OnReceiveResult is never called within the test case. 我正在尝试使用ResultReceiver但问题是在OnReceiveResult中永远不会调用OnReceiveResult (I also tried creating the ResultReceiver with new Handler() as the argument insetad of null but with the same result. (我还尝试使用new Handler()创建ResultReceiver作为null的参数insetad,但结果相同。

what am I doing wrong? 我究竟做错了什么? what is the proper way to test an IntentService ? 测试IntentService的正确方法是IntentService

this is the service: 这是服务:

public class MyService extends IntentService {

public MyService() {
    super("MyService");
}

public MyService(String name) {
    super(name);
}

@Override
protected void onHandleIntent(Intent intent) {
    final int action = intent.getIntExtra("action", 0);
    final int request = intent.getIntExtra("request", 0);
    final ResultReceiver receiver = (ResultReceiver) intent.getExtras().get("receiver");

    if (receiver == null) {
        return;
    }

    if (action == 0 || request == 0) {
        receiver.send(0, null);

        return;
    }
}

} }

and this is the test: 这是测试:

public void testHandleInvalidRequests() {
    ResultReceiver receiver = new ResultReceiver(null) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            fail();
        }   
    };

    Intent intent = new Intent(mContext, MyService.class);
    intent.putExtra("receiver", receiver);
    startService(intent);

}

I successfully managed to test my IntentService and I will show you conceptually how I did it. 我成功地设法测试了我的IntentService ,我将在概念上向您展示我是如何做到的。

First, you extend the Android Service Testing class: ServiceTestCase<MyIntentService> . 首先,扩展Android Service Testing类: ServiceTestCase<MyIntentService> Then you basically start the IntentService as you did using startService(intent) . 然后你基本上就像使用startService(intent)一样启动IntentService

Since the service under test is an IntentService , it will do all work in a spawned worker thread. 由于被测服务是一个IntentService ,它将在生成的工作线程中完成所有工作。 If you do not block your test thread then your test method will immediately do assertions that will obviously fail since the test work in the background has probably not finished yet. 如果你没有阻止你的测试线程,那么你的测试方法会立即做出明显失败的断言,因为后台的测试工作可能还没有完成。 Eventually, the test method will return and your test will fail. 最终,测试方法将返回,您的测试将失败。

What you need to do is to block your test thread after startService . 您需要做的是在startService之后阻止您的测试线程。 Do this using a ReentrantLock and a Condition calling await() on it. 使用ReentrantLock和条件调用await()来执行此操作。

The IntentService then executes onHandleIntent in the background. IntentService然后执行onHandleIntent的背景。 I suggest you extend your IntentService and override onHandleIntent , calling super.onHandleIntent() and after that, signal your test thread that the work has been done. 我建议你扩展你的IntentService并覆盖onHandleIntent ,调用super.onHandleIntent()然后,告诉你的测试线程工作已经完成。 Do this on the same lock and condition used for blocking the testing thread. 在用于阻止测试线程的相同锁和条件上执行此操作。

If startService() in the test file extends ServiceTestCase<> , I've found in Android Studio 1.1's test facility that ServiceTestCase does not instantiate an IntentService object through onHandleIntent() . 如果测试文件中的startService()扩展了ServiceTestCase<> ,我在Android Studio 1.1的测试工具中发现ServiceTestCase没有通过onHandleIntent()实例化一个IntentService对象。
See Android ServiceTestCase for IntentService for more info. 有关详细信息,请参阅IntentService的Android ServiceTestCase

I know this is old, but as I had the same kind of problem, I'll post here how I finally managed to run a test on an IntentService . 我知道这是旧的,但由于我遇到了同样的问题,我将在这里发布我最终如何设法在IntentService上运行测试。 As @Joerg said, it is a threading issue. 正如@Joerg所说,这是一个线程问题。

public class MyServiceTest extends ServiceTestCase<MyService> {
    public MyServiceTest() {
        super(MyService.class);
    }

    public void testOnHandleIntent() throws Exception {
        Looper.prepare();
        final CountDownLatch latch = new CountDownLatch(1);

        ResultReceiver receiver = new ResultReceiver(new Handler()) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                latch.countDown();

                assertEquals(resultCode, 0);
                assertNull(resultData);
                fail();

                Looper.myLooper().quit();
            }
        };

        Intent intent = new Intent(getSystemContext(), MyService.class);
        intent.putExtra("receiver", receiver);
        getSystemContext().startService(intent);

        Looper.loop();

        assertThat(latch.getCount(), is(0L));
    }
}

The Looper and Handler classes are necessary so that the callback has a thread to be called on. LooperHandler类是必需的,以便回调有一个要调用的线程。 The latch is there only as an example of a lock and as a means to assert that the code passed by the callback before the end of the test method. 锁存器仅作为锁的示例,并且作为在测试方法结束之前断言回调传递的代码的手段。

If the quit() method of the Looper is not called, the test hangs. 如果未调用Looperquit()方法,则测试将挂起。

ServiceTestCase is deprecated on the latest versions of Android, but the replacement ( ServiceTestRule ) doesn't support IntentService ... ServiceTestCase在最新版本的Android上已弃用,但替换( ServiceTestRule )不支持IntentService ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM