【发布时间】:2013-05-28 12:56:26
【问题描述】:
我正在尝试改进我所做的一些单元测试,所以我正在使用 mockito 来模拟一些对象。所以现在我有两个问题:我是否应该尝试模拟 AsyncTask 以及(如果是)如何使用这个模拟对象来调用模拟对象的 doInBackground() 方法?
我已经尝试了几件事,但仍然无法正常工作。我的测试仍然给我一个断言失败:
AsyncTask 的执行方式(在 StudioActivity.java 中):
.....
LocationTask task = new LocationTask();
task.execute((LocationManager) this.getSystemService(Context.LOCATION_SERVICE));
我的异步任务(在 StudioActivity.java 中):
.....
public class LocationTask extends AsyncTask<LocationManager, Void, String> {
private LocationManager mLocationManager;
// private TextView mLocText;
@Override
protected void onPreExecute() {
super.onPreExecute();
// mLocText = (TextView) findViewById(R.id.textView_location);
// mLocText.setVisibility(View.VISIBLE);
}
@Override
public String doInBackground(LocationManager... params) {
mLocationManager = params[0];
Location loc = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Geocoder gcd = new Geocoder(getApplicationContext(), Locale.getDefault());
List<Address> addresses;
try {
addresses = gcd.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1);
if (addresses.size() > 0) {
return (addresses.get(0).getLocality() + ", " + addresses.get(0).getCountryName());
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
mPreviewFragment.setLocation(result);
mLocation = result;
}
}
这是我尝试过的。
我的测试方法(在 TestStudioActivity.java 中):
@UiThreadTest
public void testGeolocalistationLabel() throws InterruptedException, ExecutionException{
LocationTask mockLocationTask = mock(StudioActivity.LocationTask.class);
when(mockLocationTask.doInBackground((LocationManager[]) any())).thenReturn("JUnit, Location");
mStudioBoastPreviewFragment.getGeoloc().performClick();
assertEquals("JUnit, Location",mStudioBoastPreviewFragment.getGeolocTextView().getText());
verify(mockLocationTask).doInBackground((LocationManager[]) any());
}
或
@UiThreadTest
public void testGeolocalistationLabel() throws InterruptedException, ExecutionException{
LocationTask mockLocationTask = mock(StudioActivity.LocationTask.class);
when(mockLocationTask.doInBackground((LocationManager) mStudioActivity.getSystemService(Context.LOCATION_SERVICE))).thenReturn("JUnit, Location");
mStudioBoastPreviewFragment.getGeoloc().performClick();
assertEquals("JUnit, Location",mStudioBoastPreviewFragment.getGeolocTextView().getText());
verify(mockLocationTask).doInBackground((LocationManager) mStudioActivity.getSystemService(Context.LOCATION_SERVICE));
}
失败:
junit.framework.AssertionFailedError: expected:<JUnit, Location> but was:<>
at com.c4mprod.bhost.test.TestStudioActivity.testGeolocalistationLabel(TestStudioActivity.java:255)
没有模拟,它正在工作。但是测试执行时间很长。这就是我想使用 Mockito 的原因:提高测试速度并避免连接问题或服务器错误。我只是想测试一下位置是否显示在mStudioBoastPreviewFragment.getGeolocTextView()中。
在这两种情况下,我都有断言失败,所以我想知道哪种方法最好,以及如何使用它来模拟这个doInBackground()。或者,如果有另一种模拟 AsyncTask 的方法。
感谢您的帮助!
【问题讨论】:
-
我不确定我是否正确理解了您的测试。您要测试的课程是什么? “mStudioBoastPreviewFragment”还是 LocationTask?我看不到您的模拟 LocationTask 是如何注入“mStudioBoastPreviewFragment”的。从我可以看到你的嘲笑 LocationTask 根本没有使用。
-
@joerx mStudioBoastPreviewFragment 是一个片段,其中包含我要测试的 TextView。这个片段是一个名为 StudioActivity 的 Activity 的一部分,LocationTask 是 StudioActivity 的一个内部类。当我单击 StudioBoastPreviewFragment 中的 ToggleButton 时,这将启动 AsyncTask LocationTask,它将定位用户并在我之前提到的 TextView 中显示他的位置。所以回答你的问题:我正在测试的类是 StudioBoastPreviewFragment。
标签: android junit android-asynctask mockito