ActivityUnitTestCase和Activity#runOnUiThread

Tra*_*vis 6 testing android

我的测试侧重于AsyncTask完成并验证后续Activity是否已启动.

众所周知,除非AsyncTask是从UI线程实例化并执行的,否则不会调用AsyncTask#onPostExecute,因此调用AsyncTask的我的(测试可见)方法会通过必要的预防措施来确保这种行为 - 通过Runnable立即运行if在UI线程上或计划在UI线程上运行.

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

附加物:

  • 测试在ActivityInstrumentationTestCase2类下运行,但我无法访问ActivityUnitTestCase#getStartedActivityIntent.我知道Instrumentation.ActivityMonitor,这是一个非解决方案.
  • 定于ActivityUnitTestCase#runTestOnUiThread的Runnable 不要在UI线程上运行.
  • 我不打算重新定义我的测试.
  • 奇怪的是,ActivityUnitTestCase#startActivity在UI线程上调用Activity#onCreate NOT.

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

// 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);
            }
         });
    }
Run Code Online (Sandbox Code Playgroud)

在LogCat中,我们将看到:

A | Running on UI Thread? true
B | Running on UI Thread? false
Run Code Online (Sandbox Code Playgroud)

Tra*_*vis 4

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

public void testThatRequiresUiThread() {

    runTestOnUiThread(new Runnable() {

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

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

    // rest of test...
}
Run Code Online (Sandbox Code Playgroud)

产量

A | Running on UI Thread? true
B | Running on UI Thread? true
Run Code Online (Sandbox Code Playgroud)