使用 Android 测试框架进行 Android AsyncTask 测试 [英] Android AsyncTask testing with Android Test Framework

查看:18
本文介绍了使用 Android 测试框架进行 Android AsyncTask 测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的 AsyncTask 实现示例,但在使用 Android JUnit 框架对其进行测试时遇到了问题.

I have a very simple AsyncTask implementation example and am having problem in testing it using Android JUnit framework.

当我在普通应用程序中实例化并执行它时,它工作得很好.但是,当它从任何 Android 测试框架类(即 AndroidTestCaseActivityUnitTestCaseActivityInstrumentationTestCase2 等)它的行为很奇怪:

It works just fine when I instantiate and execute it in normal application. However when it's executed from any of Android Testing framework classes (i.e. AndroidTestCase, ActivityUnitTestCase, ActivityInstrumentationTestCase2 etc) it behaves strangely:

  • 正确执行doInBackground()方法
  • 然而,它不会调用任何通知方法(onPostExecute()onProgressUpdate() 等)——只是默默地忽略它们而不显示任何错误.
  • It executes doInBackground() method correctly
  • However it doesn't invokes any of its notification methods (onPostExecute(), onProgressUpdate(), etc) -- just silently ignores them without showing any errors.

这是一个非常简单的 AsyncTask 示例:

This is very simple AsyncTask example:

package kroz.andcookbook.threads.asynctask;

import android.os.AsyncTask;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.Toast;

public class AsyncTaskDemo extends AsyncTask<Integer, Integer, String> {

AsyncTaskDemoActivity _parentActivity;
int _counter;
int _maxCount;

public AsyncTaskDemo(AsyncTaskDemoActivity asyncTaskDemoActivity) {
    _parentActivity = asyncTaskDemoActivity;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
    _parentActivity._progressBar.setVisibility(ProgressBar.VISIBLE);
    _parentActivity._progressBar.invalidate();
}

@Override
protected String doInBackground(Integer... params) {
    _maxCount = params[0];
    for (_counter = 0; _counter <= _maxCount; _counter++) {
        try {
            Thread.sleep(1000);
            publishProgress(_counter);
        } catch (InterruptedException e) {
            // Ignore           
        }
    }
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    int progress = values[0];
    String progressStr = "Counting " + progress + " out of " + _maxCount;
    _parentActivity._textView.setText(progressStr);
    _parentActivity._textView.invalidate();
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    _parentActivity._progressBar.setVisibility(ProgressBar.INVISIBLE);
    _parentActivity._progressBar.invalidate();
}

@Override
protected void onCancelled() {
    super.onCancelled();
    _parentActivity._textView.setText("Request to cancel AsyncTask");
}

}

这是一个测试用例.这里 AsyncTaskDemoActivity 是一个非常简单的 Activity,它提供了用于在模式下测试 AsyncTask 的 UI:

This is a test case. Here AsyncTaskDemoActivity is a very simple Activity providing UI for testing AsyncTask in mode:

package kroz.andcookbook.test.threads.asynctask;
import java.util.concurrent.ExecutionException;
import kroz.andcookbook.R;
import kroz.andcookbook.threads.asynctask.AsyncTaskDemo;
import kroz.andcookbook.threads.asynctask.AsyncTaskDemoActivity;
import android.content.Intent;
import android.test.ActivityUnitTestCase;
import android.widget.Button;

public class AsyncTaskDemoTest2 extends ActivityUnitTestCase<AsyncTaskDemoActivity> {
AsyncTaskDemo _atask;
private Intent _startIntent;

public AsyncTaskDemoTest2() {
    super(AsyncTaskDemoActivity.class);
}

protected void setUp() throws Exception {
    super.setUp();
    _startIntent = new Intent(Intent.ACTION_MAIN);
}

protected void tearDown() throws Exception {
    super.tearDown();
}

public final void testExecute() {
    startActivity(_startIntent, null, null);
    Button btnStart = (Button) getActivity().findViewById(R.id.Button01);
    btnStart.performClick();
    assertNotNull(getActivity());
}

}

所有这些代码都工作得很好,除了 AsyncTask 在 Android 测试框架内执行时不会调用它的通知方法.有什么想法吗?

All this code is working just fine, except the fact that AsyncTask doesn't invoke it's notification methods when executed by within Android Testing Framework. Any ideas?

推荐答案

我在实施一些单元测试时遇到了类似的问题.我必须测试一些与 Executors 一起工作的服务,我需要让我的服务回调与来自我的 ApplicationTestCase 类的测试方法同步.通常测试方法本身在回调被访问之前完成,所以通过回调发送的数据不会被测试.尝试应用 @UiThreadTest bust 仍然无效.

I met a similar problem while implementing some unit-test. I had to test some service which worked with Executors, and I needed to have my service callbacks sync-ed with the test methods from my ApplicationTestCase classes. Usually the test method itself finished before the callback would be accessed, so the data sent via the callbacks would not be tested. Tried applying the @UiThreadTest bust still didn't work.

我找到了以下方法,有效,我仍然在使用它.我只是使用 CountDownLatch 信号对象来实现等待通知(您可以使用 synchronized(lock){... lock.notify();},但这会导致代码丑陋)机制.

I found the following method, which worked, and I still use it. I simply use CountDownLatch signal objects to implement the wait-notify (you can use synchronized(lock){... lock.notify();}, however this results in ugly code) mechanism.

public void testSomething(){
final CountDownLatch signal = new CountDownLatch(1);
Service.doSomething(new Callback() {

  @Override
  public void onResponse(){
    // test response data
    // assertEquals(..
    // assertTrue(..
    // etc
    signal.countDown();// notify the count down latch
  }

});
signal.await();// wait for callback
}

这篇关于使用 Android 测试框架进行 Android AsyncTask 测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆