2012-03-14 122 views
6

我的测试着重于一个AsyncTask完成并验证后续活动已启动。ActivityUnitTestCase和Activity#runOnUiThread

已知AsyncTask#onPostExecute不会被调用,除非AsyncTask被实例化并从UI线程执行,所以调用AsyncTask的我的(测试可见)方法需要通过必要的预防措施来确保这种行为 - 通过Runnable如果在UI线程上或者计划在UI线程上运行,则会立即运行。

当从ActivityUnitTestCase测试中调用此方法时,通过Activity#runOnUiThread实例化并执行此AsyncTask的Runnable最终在UI线程以外的线程上运行。 有没有办法确保这个Runnable将在Activity的UI线程上执行?

附录:

  • 试运行下ActivityInstrumentationTestCase2 类如希望的那样,但我没有访问 ActivityUnitTestCase#getStartedActivityIntent。我知道 Instrumentation.ActivityMonitor,这是一个非解决方案。
  • 在ActivityUnitTestCase上计划的Runnables#runTestOnUiThread do在UI 线程上运行。
  • 我不想重新定义我的测试。
  • 奇怪的是,ActivityUnitTestCase#startActivity调用Activity#onCreate而不是在UI线程上。

编辑:这是一个位的(未经测试)的代码,演示了问题的实质:

// ExampleActivityTests.java 

class ExampleActivityTests : public ActivityUnitTestCase <ExampleActivity> { 

    public void testThatRequiresUiThread() { 

     startActivity (new Intent(), null, null); 
     // ...call instrumentation onStart, onResume... 

     runTestOnUiThread(new Runnable() { 
      public void run() { 
       boolean isUiThread = Thread.currentThread() == Looper.getMainLooper().getThread(); 
       Log.d ("A", "Running on UI Thread? " + isUiThread); 
      } 
     }); 

     getActivity().methodRequiringUiThread(); 

     // assertions here... 
    } 
} 

// ExampleActivity.java -- just the relevant method 

    public void methodRequiringUiThread() { 

     runOnUiThread(new Runnable() { 
      public void run() { 
       boolean isUiThread = Thread.currentThread() == Looper.getMainLooper().getThread(); 
       Log.d ("B", "Running on UI Thread? " + isUiThread); 
      } 
     }); 
    } 

在logcat中,我们会看到:

A | Running on UI Thread? true 
B | Running on UI Thread? false 
+1

通过阅读您的语句_弄得有点“通过一个Runnable立即运行,如果在UI线程或计划在UI线程上运行” _,更好地附着一些代码片段来澄清你的问题。 – yorkw 2012-03-14 00:37:00

+0

也许这个陈述太详细地描述了实现 - 它的目的仅仅是开车回家,我确实确保在UI线程上创建和执行AsyncTask。我可以添加代码来演示我正面临的问题,但我会在省略此方面的情况下执行此操作。 – Travis 2012-03-14 02:07:00

回答

4

上调用ActivityUnitTestCase#startActivity UI线程解决了我的问题。

public void testThatRequiresUiThread() { 

    runTestOnUiThread(new Runnable() { 

     @Override 
     public void run() { 
      startActivity(new Intent(), null, null); 
     } 
    }); 

    // ... 
    getActivity().methodRequiringUiThread(); 

    // rest of test... 
} 

产生

A | Running on UI Thread? true 
B | Running on UI Thread? true