监视 AsyncTask 不起作用

Spying an AsyncTask doesn't work

我正在测试 AsyncTask。我想将 HttpURLConnection 存根到 return 我的模拟对象。我就是这样做的(PackageDownloader 代表一个 AsyncTask):

 ...
 PackageDownloader packageDownloader = new PackageDownloader();
 packageDownloader.setParameters(URL, downloadFolder, downloadProgressCallback);
 PackageDownloader mPackageDownloader = spy(packageDownloader);
 HttpURLConnection connectionMock = Mockito.mock(HttpURLConnection.class);
 doReturn(0).when(connectionMock).getContentLength();
 doReturn(connectionMock).when(mPackageDownloader).createConnection(Mockito.any(URL.class));
 mPackageDownloader.execute();
 mPackageDownloader.get();

这是PackageDownloader:

public HttpURLConnection createConnection(URL url) throws IOException {
    HttpURLConnection connection;
    connection = (HttpURLConnection) url.openConnection();
    return connection;
}

@Override
protected DownloadResult doInBackground(Void... params) {
    HttpURLConnection connection;
    URL downloadUrl = new URL(downloadUrlString);
    connection = createConnection(downloadUrl);
    long totalBytes = connection.getContentLength();
    ...

在这里,createConnection return是真实的对象,不是模拟对象,我不明白为什么。

好吧,我找到了一个解决方案,但还没有找到它为何如此有效的解释。 没有工作的原因是 doInBackground 方法是异步的,我想,所以我不得不通过反射直接调用它,像这样:

 Method method = mPackageDownloader.getClass().getMethod("doInBackground", Void[].class);
 method.invoke(mPackageDownloader, new Void[] {null});

您可以使用 robolectric 来测试异步任务而不是反射。在 ShadowApplication.runBackgroundTasks() 之后应该调用 doInBackground() 方法。

@RunWith(RobolectricTestRunner.class)
public class AcknowledgeAppRemovedTaskTest {

    @Test
    public void execute_shouldOpenInputStreamOfConnection() throws IOException {
        DownloadTask spy = spy(new DownloadTask());
        HttpURLConnection connectionMock = mock(HttpURLConnection.class);
        doReturn(connectionMock).when(spy).createConnection(any(URL.class));

        spy.execute();
        ShadowApplication.runBackgroundTasks();
        verify(connectionMock).getInputStream();
    }
}


class DownloadTask extends AsyncTask<Void, Void, Void> {}

    public HttpURLConnection createConnection(URL url) throws IOException {
        return (HttpURLConnection) url.openConnection();
    }

    @Override
    protected Void doInBackground(Void... voids) {
        try {
            HttpURLConnection urlConnection = createConnection(new URL("https://www.google.com/"));
            urlConnection.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

https://github.com/robolectric/robolectric/blob/master/robolectric/src/test/java/org/robolectric/shadows/ShadowAsyncTaskTest.java

https://groups.google.com/forum/#!topic/mockito/mqF21aqTi5g