Макет веб-сервера и модернизация с обратным вызовом

#android #retrofit #mockwebserver

#Android #модернизация #макет веб-сервера

Вопрос:

Я хотел бы имитировать сетевое взаимодействие с помощью MockWebServer. К сожалению, модифицированные обратные вызовы никогда не вызываются. Мой код:

     MockWebServer server = new MockWebServer();
    server.enqueue(new MockResponse().setResponseCode(200).setBody("{}"));
    server.play();

    RestAdapter restAdapter = new RestAdapter.Builder().setConverter(new MyGsonConverter(new Gson()))
            .setEndpoint(server.getUrl("/").toString()).build();

    restAdapter.create(SearchService.class).getCount(StringUtils.EMPTY,
            new Callback<CountContainer>() {

                @Override
                public void success(CountContainer countContainer, Response response) {
                    System.out.println("success");
                }

                @Override
                public void failure(RetrofitError error) {
                    System.out.println("error");
                }
            });

    server.shutdown();
  

Когда я использую модернизацию без обратных вызовов, это работает.

Комментарии:

1. Вам нужно прикрепить свой обратный вызов, ПРЕЖДЕ чем делать server.play() это?

2. Когда я меняю порядок, это вызывает исключение java.lang. Исключение IllegalStateException: не удается получить порт перед вызовом play ()

Ответ №1:

Имея a Callback , вы указываете Retrofit вызвать запрос и вызвать обратный вызов асинхронно. Это означает, что ваш тест завершается до того, как что-либо произойдет.

Есть два способа заставить это работать:

  • Используйте блокировку в конце теста и подождите, пока не будет вызван один из методов обратного вызова.
  • Передайте экземпляр синхронного Executor (тот, который просто вызывает .run() немедленно) в setExecutors on RestAdapter.Builder , чтобы фоновые вызовы и вызовы обратного вызова выполнялись синхронно.

Комментарии:

1. 1 спасибо, синхронная работа отлично работает. executors Разве блокировка не блокирует основной поток и, следовательно, не позволяет выполнять обратные вызовы (в основном потоке), и поэтому блокировка никогда не снимается? «Lock» я думаю о чем-то вроде CountDownLatch

2. Это не работает с retrofit 2. Как мне заставить его работать в модернизации 2?

Ответ №2:

Для модернизации 2 смотрите Ответ здесь: https://github.com/square/retrofit/issues/1259 Вы можете предоставить синхронного исполнителя OkHttpClient (через его диспетчера) и настроить этот клиент на модернизацию.Конструктор. Вы также можете установить тот же исполнитель для callbackExecutor.

Например:

 CurrentThreadExecutor currentThreadExecutor = new CurrentThreadExecutor();
okhttp3.Dispatcher dispatcher = new okhttp3.Dispatcher(currentThreadExecutor);
OkHttpClient okHttpClient = new 
OkHttpClient.Builder().dispatcher(dispatcher).build();

new Retrofit.Builder()
        .client(okHttpClient)
        .baseUrl(httpUrl)
        .addConverterFactory(JacksonConverterFactory.create())
        .callbackExecutor(currentThreadExecutor)
        .build();
  

Пример реализации CurrentThreadExecutor:
https://gist.github.com/vladimir-bukhtoyarov/38d6b4b277d0a0cfb3af

Комментарии:

1. Это должно быть принято. Хороший материал.

Ответ №3:

В качестве альтернативы вы можете использовать Mockinizer с MockWebServer:

 OkHttpClient.Builder()
        .addInterceptor(loggingInterceptor)
        .mockinize(mocks) // <-- just add this line
        .build()
  

И запросы / ответы, которые вы хотите имитировать, вы можете определить в mocks значении. В вашем случае это будет выглядеть примерно так:

 package com.appham.mockinizer.demo

import com.appham.mockinizer.RequestFilter
import okhttp3.mockwebserver.MockResponse

val mocks: Map<RequestFilter, MockResponse> = mapOf(

    RequestFilter("/") to MockResponse().apply {
        setResponseCode(200)
        setBody("""{}""")
    }

)
  

Смотрите https://github.com/donfuxx/Mockinizer