У меня есть функция, которую я хочу проверить, которая работает в обратном вызове okHttp. Я пытаюсь проверить его с помощью Robolectrics, но обратный вызов никогда не выполняется. Я предполагаю, что это потому, что тест движется по запросу, не дожидаясь okHttp для возврата. До сих пор я пробовал:
ShadowLooper.pauseMainLooper(); Robolectric.flushBackgroundScheduler(); ShadowLooper.unPauseMainLooper();
Но это не сработало. Какие-либо предложения?
РЕДАКТИРОВАТЬ:
Вот пример моего кода:
ApiClient.sendSomeDataToServer(data, callback);
Где ApiClient – это вспомогательный класс, содержащий okHttp-клиент. Вызов sendSomeDataToServer API выглядит примерно так:
public static void sendSomeDataToServer(MyObject data, Callback callback){ final Request request = new Request.Builder() .url(API_SOME_URL) .post(RequestBody.create(JSON, myObject.getAsJson().toString())) .build(); sHttpClient.newCall(request).enqueue(callback); }
Где sHttpClient – инициализированный OkHttpClient.
Я могу проверить выполнение выше, заставив Thread.sleep(5000)
внутри моего тестового кода и предоставив пользовательский обратный вызов. Код, который я пытаюсь проверить, находится внутри обратного вызова. Любые предложения, как я могу это проверить? Я действительно не хочу менять основной код, чтобы он соответствовал тестовой структуре – должен быть наоборот.
Предположим, у вас есть следующий код. Интерфейс:
@GET("/user/{id}/photo") void listUsers(@Path("id") int id, Callback<Photo> cb);
Реализация:
public void fetchData() { RestAdapter restAdapter = new RestAdapter.Builder() .setServer("baseURL") .build(); ClientInterface service = restAdapter.create(ClientInterface.class); Callback<Photo> callback = new Callback<Photo>() { @Override public void success(Photo o, Response response) { } @Override public void failure(RetrofitError retrofitError) { } }; service.listUsers(435, callback); }
Прежде всего вам нужно изменить экземпляр service
инъекцию service
(в качестве параметра или поля). Я сделаю это как параметр:
public void fetchData(ClientInterface clients) { }
После этого текст довольно тривиален:
@Test public void checkThatServiceSuccessIsProcessed() { ClientInterface mockedClients = mock(ClientInterface.class); activity.fetchData(mockedClients); // get callback ArgumentCaptor<Callback<Photo>> captor = (ArgumentCaptor<Callback<Photo>>)ArgumentCaptor.forClass(Callback.class); verify(mockedInterface).listUsers(anything(), captor.capture()); Callback<Photo> passedCallback = captor.value(); // run callback callback.success(...); // check your conditions }
Используемая библиотека для издевательств и проверки – Mockito
.
Будет одно предупреждение с созданием экземпляра из-за дженериков, но оно может быть @Captor
если вы будете использовать аннотацию @Captor
вместо создания захвата руками.
Инъекция параметров не идеальна, особенно для случая активности. Это было использовано для упрощения примера. Подумайте о правильной инъекции с библиотекой или без нее. Я бы посоветовал вам попробовать Dagger
для инъекций
Вы можете использовать ArgumentCaptor (класс Mockito). Ссылка: http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html