Junit 如何在android中对异步任务进行单元测试

Junit 如何在android中对异步任务进行单元测试,junit,android-asynctask,android-junit,Junit,Android Asynctask,Android Junit,考虑下面的代码。我如何在不使用第三方库的情况下测试此功能?断言行永远不会执行,因为它是另一个线程,vm停止运行。非常感谢 public class FileParserTask extends AsyncTask<File, Void, ArrayList<City>> { private FileParserResult mResult; public interface FileParserResult { void onFinis

考虑下面的代码。我如何在不使用第三方库的情况下测试此功能?断言行永远不会执行,因为它是另一个线程,vm停止运行。非常感谢

public class FileParserTask extends AsyncTask<File, Void, ArrayList<City>> {

    private FileParserResult mResult;

    public interface FileParserResult {
        void onFinish(ArrayList<City> cities);
    }

    public FileParserTask(final FileParserResult result) {
        mResult = result;
    }

    @Override
    protected ArrayList<City> doInBackground(File... files) {
        ArrayList<City> cities = new ArrayList<>();
        try {
            InputStream is = new FileInputStream(files[0]);
            JsonReader reader = new JsonReader(new InputStreamReader(is, "UTF-8"));
            reader.beginArray();
            while (reader.hasNext()) {
                City city = new Gson().fromJson(reader, City.class);
                cities.add(city);
            }
            reader.endArray();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        Collections.sort(cities, (o1, o2) -> o1.getName().compareTo(o2.getName()));
        mResult.onFinish(cities);
        return cities;
    }
}

正如您所说,问题在于异步任务通过
ExecutorService
在后台线程中运行。与
Future
类似,它提供了一个
get()
方法,该方法将等待并返回结果

new FileParserTask(cities -> {
    Assert.assertEquals("Input should give back 200 results", 3, cities.size());
}).execute(file).get();

尽管您需要测试的代码:

Assert.assertEquals("Input should give back 200 results", 3, cities.size());
正在
异步任务
中运行,这与单元测试无关
AsyncTask
很可能已经过Google的广泛测试,因此您知道它将作为一个
AsyncTask
工作。真正的测试似乎是需要在后台运行的功能,即
doInBackground
中包含的业务逻辑

从业务逻辑的角度考虑,需要填充
ArrayList
,并将其传播到应用程序。Android更喜欢在后台线程上完成这项工作,传播可以通过通知等方式处理,这两种方式都已经过测试,并由Google发布,因此您不需要在单元测试中包含它们。如何填充
ArrayList
是真正的单元测试

AsyncTask
与集成测试相关,但您很可能要测试应用程序的另一个方面,即它显示的内容,而不是从后台线程接收的内容


因此,对于单元测试,我将重构
doInBackground
中的代码,以便它可以独立于Android希望它如何运行进行测试。

对不起,您是否覆盖了AsyncTask的onPostExecute方法。 您将保留结果处理程序,但不会在任何地方使用它

@Override
protected void onPostExecute(Object result) {
    mResult.processFinish(result);
}

至于这个断言,它看起来很好,因为它是。

不,这不起作用。测试运行失败:由于“进程崩溃”,检测运行失败。这可能有助于忘记方法规范onPostExecute(ArrayList结果)中的类型
@Override
protected void onPostExecute(Object result) {
    mResult.processFinish(result);
}