Поскольку я не получил никакого ответа на свой вопрос, я отвечу на свой вопрос.Я решил пойти с другим подходом, чем в примере кода моего вопроса.Основная схема моего нового подхода:
Я переключил свой базовый тестовый класс на ActivityInstrumentationTestCase2
Я создал MockHttpClient
класс, которыйЯ внедряю в свой код, и этот MockHttpClient
возвращает успешный HttpResponse
с объектом ответа, содержащим мои данные JSON.Класс MockHttpClient
реализует интерфейс HttpClient
и возвращает null
для всех методов, кроме методов execute()
, которые должны возвращать объект HttpResponse
.
Поскольку ListFragment
Я проверяю регистры BroadcastReceiver
, чтобы определить, что служба извлечения данных завершена, я также регистрирую BroadcastReceiver
в своем тесте.Я блокирую свой тест с помощью CountDownLatch
до получения трансляции.
Когда трансляция получена, я использую Thread.sleep(500)
, чтобы позволить моей активности обновить ListView
.После этого я выполняю свои утверждения против ListView
.
Я аннотировал свой тест с помощью FlakyTest(tolerance=5)
, который выполняет тест до 5 раз, когда утверждения не выполняются.
Я не уверен, что это хороший подход, поэтому, пожалуйста, не стесняйтесь оставлять комментарии.Но пока это работает.Чтобы завершить мой ответ, новый код для моего теста:
TEST CLASS
public class TopscorersActivityTest extends ActivityInstrumentationTestCase2<TopscorersActivity> {
public static final String JSON = "["
+ "{\"position\": 1, \"name\": \"Bas Dost\", \"club\": \"sc Heerenveen\", \"goals\": \"16\" },"
+ "{\"position\": 2, \"name\": \"Dries Mertens\", \"club\": \"PSV\", \"goals\": \"13\"},"
+ "{\"position\": 3, \"name\": \"Luuk de Jong\", \"club\": \"FC Twente\", \"goals\": \"12\"}"
+ "]";
private TopscorersActivity mActivity;
private ListView mListView;
public TopscorersActivityTest() {
super("com.example.package", TopscorersActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
ConnectivityUtils.setHttpClient(MockHttpClient.createInstance(JSON));
mActivity = getActivity();
mListView = (ListView) getActivity().findViewById(android.R.id.list);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
ConnectivityUtils.setHttpClient(null);
}
@MediumTest
public void testPreconditions() {
assertNotNull(mActivity);
assertNotNull(mListView);
assertEquals(0, mListView.getFirstVisiblePosition());
}
@FlakyTest(tolerance=5)
@LargeTest
public void testListItemsPopulatedCorrectly() throws InterruptedException {
waitForBroadcast(mActivity, TopscorersService.BROADCAST_ACTION, Intent.CATEGORY_DEFAULT);
assertEquals(3, mListView.getCount());
// First list item
View view = mListView.getChildAt(0);
assertNotNull(view);
TextView positionTextView = (TextView) view.findViewById(R.id.topscorerPositionTextView);
TextView nameTextView = (TextView) view.findViewById(R.id.topscorerNameTextView);
TextView goalsTextView = (TextView) view.findViewById(R.id.topscorerGoalsTextView);
assertEquals("1", positionTextView.getText());
assertEquals("16", goalsTextView.getText());
assertEquals(
Html.fromHtml("Bas Dost<br /><i>sc Heerenveen</i>").toString(),
nameTextView.getText().toString()
);
// Second list item
view = mListView.getChildAt(1);
assertNotNull(view);
positionTextView = (TextView) view.findViewById(R.id.topscorerPositionTextView);
nameTextView = (TextView) view.findViewById(R.id.topscorerNameTextView);
goalsTextView = (TextView) view.findViewById(R.id.topscorerGoalsTextView);
assertEquals("2", positionTextView.getText());
assertEquals("13", goalsTextView.getText());
assertEquals(
Html.fromHtml("Dries Mertens<br /><i>PSV</i>").toString(),
nameTextView.getText().toString()
);
// Third list item
view = mListView.getChildAt(2);
assertNotNull(view);
positionTextView = (TextView) view.findViewById(R.id.topscorerPositionTextView);
nameTextView = (TextView) view.findViewById(R.id.topscorerNameTextView);
goalsTextView = (TextView) view.findViewById(R.id.topscorerGoalsTextView);
assertEquals("3", positionTextView.getText());
assertEquals("12", goalsTextView.getText());
assertEquals(
Html.fromHtml("Luuk de Jong<br /><i>FC Twente</i>").toString(),
nameTextView.getText().toString()
);
}
private void waitForBroadcast(Context context, String action, String category) throws InterruptedException {
final CountDownLatch signal = new CountDownLatch(1);
IntentFilter intentFilter = new IntentFilter(action);
intentFilter.addCategory(category);
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
signal.countDown();
}
};
context.registerReceiver(broadcastReceiver, intentFilter);
signal.await(1500, TimeUnit.MILLISECONDS);
context.unregisterReceiver(broadcastReceiver);
Thread.sleep(500);
}
}
MOCK HTTP CLIENT CLASS
public class MockHttpClient implements HttpClient {
private HttpResponse mHttpResponse;
/**
* A MockHttpClient with an HTTP 1.1 200 OK response
*
* @param response
* @return
* @throws UnsupportedEncodingException
*/
public static HttpClient createInstance(String response)
throws UnsupportedEncodingException {
return createInstance(200, "OK", response);
}
/**
* A MockHttpClient with an HTTP 1.1 response
*
* @param statusCode
* @param reasonPhrase
* @param response
* @return
* @throws UnsupportedEncodingException
*/
public static HttpClient createInstance(int statusCode, String reasonPhrase, String response)
throws UnsupportedEncodingException {
return createInstance(HttpVersion.HTTP_1_1, statusCode, reasonPhrase, response);
}
/**
*
* @param version
* @param statusCode
* @param reasonPhrase
* @param response
* @return
* @throws UnsupportedEncodingException
*/
public static HttpClient createInstance(ProtocolVersion version, int statusCode, String reasonPhrase, String response)
throws UnsupportedEncodingException {
StatusLine statusLine = new BasicStatusLine(version, statusCode, reasonPhrase);
HttpResponse httpResponse = new BasicHttpResponse(statusLine);
HttpEntity httpEntity = new StringEntity(response);
httpResponse.setEntity(httpEntity);
return new MockHttpClient(httpResponse);
}
/**
* Constructor.
*
* @param httpResponse
*/
private MockHttpClient(HttpResponse httpResponse) {
mHttpResponse = httpResponse;
}
/**
*
* @param request
* @return
*/
public HttpResponse execute(HttpUriRequest request) {
return mHttpResponse;
}
@Override
public HttpResponse execute(HttpUriRequest request, HttpContext context)
throws IOException, ClientProtocolException {
return mHttpResponse;
}
@Override
public HttpResponse execute(HttpHost target, HttpRequest request)
throws IOException, ClientProtocolException {
return mHttpResponse;
}
@Override
public <T> T execute(HttpUriRequest arg0,
ResponseHandler<? extends T> arg1) throws IOException,
ClientProtocolException {
return null;
}
@Override
public HttpResponse execute(HttpHost target, HttpRequest request,
HttpContext context) throws IOException,
ClientProtocolException {
return mHttpResponse;
}
@Override
public <T> T execute(HttpUriRequest arg0,
ResponseHandler<? extends T> arg1, HttpContext arg2)
throws IOException, ClientProtocolException {
return null;
}
@Override
public <T> T execute(HttpHost arg0, HttpRequest arg1,
ResponseHandler<? extends T> arg2) throws IOException,
ClientProtocolException {
return null;
}
@Override
public <T> T execute(HttpHost arg0, HttpRequest arg1,
ResponseHandler<? extends T> arg2, HttpContext arg3)
throws IOException, ClientProtocolException {
return null;
}
@Override
public ClientConnectionManager getConnectionManager() {
return null;
}
@Override
public HttpParams getParams() {
return null;
}
}