请考虑以下代码。如何在不使用第三方库的情况下对此进行测试?断言行永远不会执行,因为它是不同的线程,并且 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);
}
}
虽然你需要测试的代码:
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希望其运行方式进行测试。
抱歉,您是否覆盖了 AsyncTask 的 onPostExecute 方法。 您保留了结果处理程序,但不在任何地方使用它。
@Override
protected void onPostExecute(Object result) {
mResult.processFinish(result);
}
至于断言,它对我来说看起来不错。
正如您所说,问题是 AsyncTask 通过ExecutorService
在后台线程中运行。 但是,与Future
一样,它提供了一种get()
方法,该方法将等待并返回结果。
new FileParserTask(cities -> {
Assert.assertEquals("Input should give back 200 results", 3, cities.size());
}).execute(file).get();