如何在android中单元测试AsyncTask

时间:2018-03-14 11:12:56

标签: junit android-asynctask android-junit

考虑以下代码。如何在不使用第三方库的情况下测试? Assert行永远不会执行,因为它是一个不同的线程,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;
    }
}

测试代码:

@RunWith(AndroidJUnit4.class)
public class CityServiceTest {

    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "cities-medium.json");

    @Test
    public void givenInputAbuThenIShouldGetXResults() throws InterruptedException {
        new FileParserTask(cities -> {
            Assert.assertEquals("Input should give back 200 results", 3, cities.size());
        }).execute(file);
    }
}

3 个答案:

答案 0 :(得分:3)

虽然您需要测试代码:

Assert.assertEquals("Input should give back 200 results", 3, cities.size());

正在AsyncTask中运行,这与单元测试无关。 AsyncTask很可能已经过Google的广泛测试,因此您知道它可以作为AsyncTask使用。真正的测试似乎是需要在后台运行的功能,即doInBackground中包含的业务逻辑。

在业务逻辑方面考虑它,需要填充ArrayList<City>并将其传播到应用程序。 Android希望在后台线程上完成此操作,并且可以通过通知等处理传播,这两者都已经过Google的测试和发布,因此您不需要将它们包含在单元测试中。如何填充ArrayList<City>是真正的单元测试。

AsyncTask与集成测试相关,但您最有可能为此测试应用程序的不同方面,即它显示的内容而不是从后台线程接收的内容。

因此,对于单元测试,我会重构doInBackground中的代码,以便可以独立于Android的运行方式进行测试。

答案 1 :(得分:1)

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

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

至于断言,它对我来说看起来不错。

答案 2 :(得分:0)

正如您所说,问题是通过ExecutorService在后​​台线程中运行的AsyncTask。与Future一样,它提供了一个等待和返回结果的get()方法。

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