首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AsyncTask.onPostExecute()在ServiceTestCase中从未被调用

AsyncTask.onPostExecute()在ServiceTestCase中从未被调用
EN

Stack Overflow用户
提问于 2011-05-19 22:03:46
回答 4查看 2.7K关注 0票数 3

我正在使用ServiceTestCase为服务编写单元测试。

该服务基本上执行一个AsyncTask,该AsyncTask执行一些工作,然后在onPostExecute()中执行其他操作。

当我在(虚拟)设备中运行和调试该服务时,它可以正常工作。

但是在扩展ServiceTestCase的测试中,我只进入了doInBackground()。一旦方法返回,onPostExecute()就不会被调用。我让测试睡眠(),所以AsyncTask有时间完成它的工作。

这是简化的服务:

代码语言:javascript
复制
public class ServiceToTest extends Service {
    private AtomicBoolean busy = new AtomicBoolean(false);

    @Override
    public IBinder onBind(final Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(final Intent intent, final int flags,
        final int startId) {
        this.handleCommand();
        return START_NOT_STICKY;
    }

    /**
    * Workaround for http://code.google.com/p/android/issues/detail?id=12117
    */
    @Override
    public void onStart(final Intent intent, final int startId) {
        this.handleCommand();
    }

    public void handleCommand() {
        new TaskToTest().execute();
    }

    public boolean isBusy() {
        return busy.get();
    }

    private class TaskToTest extends AsyncTask<Boolean, Void, TestInfo> {
        @Override
        protected void onPreExecute() {
            busy.set(true);
        }

        @Override
        protected TestInfo doInBackground(final Boolean... args) {
            return null;
        }

        @Override
        protected void onPostExecute(final TestInfo info) {
            busy.set(false);
        }
    }
}

An这是对它的测试:

代码语言:javascript
复制
public class ServiceTest extends ServiceTestCase<ServiceToTest> {
    public ServiceTest() {
        super(ServiceToTest.class);
    }

    public void testIsBusy() throws InterruptedException {
        startService(new Intent("this.is.the.ServiceToTest"));  
        ServiceToTest serviceToTest = this.getService();
        assertTrue(serviceToTest.isBusy());
        Thread.sleep(10000);
        assertFalse(serviceToTest.isBusy());
    }
}

我认为ServiceTestCase提供的环境是有限的,所以这不起作用,但是我能做些什么来使它正常工作吗?

干杯,托尔斯顿

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-05-20 02:37:57

问题是后台线程正在等待UI是“活动的”,您需要调用Looper.prepare()Looper.loop()。最好用此页来解释。

票数 1
EN

Stack Overflow用户

发布于 2011-05-20 12:04:54

因此,为了跟进我是如何让它与dmon提供的信息一起工作的。

我把我的测试改为:

public class ServiceTest extends ServiceTestCase {

代码语言:javascript
复制
public ServiceTest() {
    super(ServiceToTest.class);
}

public void testIsBusy() throws InterruptedException {

    // Starts the service and asserts that onPreExecute() was called
    ServiceTestThread serviceTestThread = new ServiceTestThread();
    serviceTestThread.start();

    // Wait for the service to start and complete doInBackground()
    // TODO Implement something smarter than this...
    Thread.sleep(1000);

    // Assert that onPostExecute() was called
    assertFalse(serviceTestThread.serviceToTest.isBusy());

}

private class ServiceTestThread extends Thread {

    ServiceToTest serviceToTest;

    public void run() {
        Looper.prepare();

        startService(new Intent("this.is.the.ServiceToTest"));

        serviceToTest = getService();

        assertTrue(serviceToTest.isBusy());

        Looper.loop();
    }

}

}

现在我将看到,使这个ServiceTestThread更通用,这样它就可以被重用了。

托尔斯顿

票数 1
EN

Stack Overflow用户

发布于 2012-06-08 22:46:18

不确定这对其他人是否有用,但这是我试图抽象Torten答案并使其更可重用的尝试。

代码语言:javascript
复制
    private synchronized boolean getWaitFlag()
    {
        return _waitFlag;
    }

    private boolean _waitFlag;

    private synchronized void setWaitFlag(boolean value)
    {
        _waitFlag = value;
    }

    private void waitForCompletionFlag() throws InterruptedException
    {
        Calendar cal = Calendar.getInstance();
        while (getWaitFlag() == false)
        {
            Thread.sleep(10);
            if (Calendar.getInstance().getTimeInMillis() - cal.getTimeInMillis() > 1000) // Wait at most 1 second
            {
                Log.e("timeout", "timed out waiting to complete task");
                break;
            }
        }
    }

private abstract class EmulatedUI extends Thread
    {
        public abstract void doWork();

        public void run()
        {
            Looper.prepare();
            doWork();
            Looper.loop();
        }
    }

public void testSomething() throws InterruptedException
{
    EmulatedUI thread = new EmulatedUI() {

        @Override
        public void doWork()
        {
            _objectToTest.someAsyncCall(new WorkCompletedCallback() {

                        @Override
                        public void onComplete()
                        {
                                   // could possibly assert things here
                            setWaitFlag(true);
                        }
                    });

        }
    };
    thread.start();
    waitForCompletionFlag();
    // assert things here since you know the async task has completed.
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6065351

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档