测试涉及 AsyncTask 中的侦听器回调的类

Test a class that involves listener callback inside AsyncTask

提问人:Falling Into Infinity 提问时间:6/30/2019 最后编辑:questionaskerFalling Into Infinity 更新时间:7/12/2019 访问量:1533

问:

我正在尝试测试在AsyncTask

监听器类:

interface LoaderListener {
    fun onByteSuccess(..., ..., ...)

    fun onByteFailure(..., ...)
}

包含 AsyncTask 的类:

class Loader {

override fun handleStreamTask(){
        InputStreamHandlingTask(..., ...).execute(byteArray)
    }

private inner class InputStreamHandlingTask constructor(
            internal var ...,
            internal var ...
        ) : AsyncTask<ByteArray, Void, ByteArray>() {

            override fun doInBackground(vararg params: ByteArray): ByteArray? {
                val response = params[0]
                .....
                return response
            }

            override fun onPostExecute(byteArray: ByteArray?) {
                   if (byteArray != null) {
                       listener.onByteSuccess(..., ..., ...)
                   } else {
                       listener.onByteFailure(..., ...)
                   }
            }

        }
}

我正在尝试进行的测试:

@Test
fun testIfListenerCalled(){
    val loader: Loader = mock()
    val loaderListener: LoaderListener = mock()

    loader.handleStreamTask()

    verify(loaderListener).onByteSuccess(..., ..., ...)
}

我目前遇到的错误:

线程中的异常...java.lang.RuntimeException:未模拟在 android.os.AsyncTask 中执行的方法。有关详细信息,请参阅 http://g.co/androidstudio/not-mocked。 在 android.os.AsyncTask.execute(AsyncTask.java)

Android junit mockito android-testing mockito-kotlin

评论

0赞 second 7/6/2019
既然没有其他人来回答这个问题,也许是时候看看一个不同的框架了......请参阅 stackoverflow.com/questions/33556172/...

答:

1赞 ahasbini 7/12/2019 #1

如果这是在本地计算机上运行的单元测试,而不是在 Android 设备上运行的单元测试,则无法模拟依赖于 Android 框架的类,例如 .相反,应该将其实现为插桩测试,而不是在 Android 设备上运行的单元测试,或者使用可以在本地计算机上模拟 Android 框架的框架。AsyncTask

更多信息请见: https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests

评论

0赞 drdaanger 7/12/2019
这是正确的。要让测试在您的设备上运行,第一步是将测试从 test 目录移至 androidTest 目录。
0赞 Sachin Kasaraddi 7/12/2019 #2

下面的示例演示了如何在 JUnit 中测试 Asynctasks。

/**
 * @throws Throwable
 */
public void testAsynTask () throws Throwable {
    // create  a signal to let us know when our task is done.
    final CountDownLatch signal = new CountDownLatch(1);

    /* Just create an in line implementation of an asynctask. Note this
     * would normally not be done, and is just here for completeness.
     * You would just use the task you want to unit test in your project.
     */
    final AsyncTask<String, Void, String> myTask = new AsyncTask<String, Void, String>() {

        @Override
        protected String doInBackground(String... arg0) {
            //Your code to run in background thread.
            return "Expected value from background thread.";
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            /* This is the key, normally you would use some type of listener
             * to notify your activity that the async call was finished.
             *
             * In your test method you would subscribe to that and signal
             * from there instead.
             */
            signal.countDown();
        }
    };

    // Execute the async task on the UI thread! THIS IS KEY!
    runTestOnUiThread(new Runnable() {

        @Override
        public void run() {
            myTask.execute("Do something");
        }
    });

    /* The testing thread will wait here until the UI thread releases it
     * above with the countDown() or 30 seconds passes and it times out.
     */
    signal.await(30, TimeUnit.SECONDS);

    // The task is done, and now you can assert some things!
    assertTrue("Expected Value", true);
}