Подтвердить что ты не робот

Android Unit Test с Retrofit2 и Mockito или Robolectric

Можно ли проверить реальный ответ от retrofit2beta4? Нужен ли мне Mockito или Robolectic?

У меня нет действий в моем проекте, это будет библиотека, и мне нужно проверить, правильно ли отвечает сервер. Теперь у меня такой код и застрял...

@Mock
ApiManager apiManager;

@Captor
private ArgumentCaptor<ApiCallback<Void>> cb;

@Before
public void setUp() throws Exception {
    apiManager = ApiManager.getInstance();
    MockitoAnnotations.initMocks(this);
}

@Test
public void test_login() {
    Mockito.verify(apiManager)
           .loginUser(Mockito.eq(login), Mockito.eq(pass), cb.capture());
    // cb.getValue();
    // assertEquals(cb.getValue().isError(), false);
}

Я могу сделать фальшивый ответ, но мне нужно проверить реальность. Это успех? Правильно ли это тело? Можете ли вы мне помочь с кодом?

4b9b3361

Ответ 1

Ответ слишком прост, чем я ожидал:

Использование CountDownLatch заставляет ваш тест ждать, пока вы не вызовете countDown()

public class SimpleRetrofitTest {

private static final String login = "[email protected]";
private static final String pass = "pass";
private final CountDownLatch latch = new CountDownLatch(1);
private ApiManager apiManager;
private OAuthToken oAuthToken;

@Before
public void beforeTest() {
    apiManager = ApiManager.getInstance();
}

@Test
public void test_login() throws InterruptedException {
    Assert.assertNotNull(apiManager);
    apiManager.loginUser(login, pass, new ApiCallback<OAuthToken>() {
        @Override
        public void onSuccess(OAuthToken token) {
            oAuthToken = token;
            latch.countDown();
        }

        @Override
        public void onFailure(@ResultCode.Code int errorCode, String errorMessage) {
            latch.countDown();
        }
    });
    latch.await();
    Assert.assertNotNull(oAuthToken);
}

@After
public void afterTest() {
    oAuthToken = null;
}}

Ответ 2

Как правило, не рекомендуется тестировать реальные серверные запросы. См. этот пост в блоге для интересной дискуссии по этой теме. По словам автора, использование вашего реального сервера является проблемой, потому что:

  • Другая движущаяся деталь, которая может прерываться с ошибкой
  • Требуется экспертиза вне домена Android для развертывания сервера и обновления его содержимого.
  • Затруднения при запуске ошибок/случаев края
  • Медленное выполнение теста (по-прежнему вызывает HTTP-вызовы)

Вы можете избежать всех вышеперечисленных проблем, используя макетный сервер, такой как OkHttp MockWebServer, чтобы имитировать реальные результаты ответа. Например:

@Test
public void test() throws IOException {
    MockWebServer mockWebServer = new MockWebServer();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(mockWebServer.url("").toString())
            //TODO Add your Retrofit parameters here
            .build();

    //Set a response for retrofit to handle. You can copy a sample
    //response from your server to simulate a correct result or an error.
    //MockResponse can also be customized with different parameters
    //to match your test needs
    mockWebServer.enqueue(new MockResponse().setBody("your json body"));

    YourRetrofitService service = retrofit.create(YourRetrofitService.class);

    //With your service created you can now call its method that should 
    //consume the MockResponse above. You can then use the desired
    //assertion to check if the result is as expected. For example:
    Call<YourObject> call = service.getYourObject();
    assertTrue(call.execute() != null);

    //Finish web server
    mockWebServer.shutdown();
}

Если вам нужно смоделировать задержки в сети, вы можете настроить свой ответ следующим образом:

MockResponse response = new MockResponse()
    .addHeader("Content-Type", "application/json; charset=utf-8")
    .addHeader("Cache-Control", "no-cache")
    .setBody("{}");
response.throttleBody(1024, 1, TimeUnit.SECONDS);

В качестве альтернативы вы можете использовать MockRetrofit и NetworkBehavior для моделирования ответов API. См. здесь пример того, как его использовать.

Наконец, если вы просто хотите протестировать свою Retrofit Service, самым простым было бы создать макетную версию, которая испускает макетные результаты для ваших тестов. Например, если у вас есть следующий сервисный интерфейс GitHub:

public interface GitHub {
    @GET("/repos/{owner}/{repo}/contributors")
    Call<List<Contributor>> contributors(
        @Path("owner") String owner,
        @Path("repo") String repo);
}

Затем вы можете создать следующие MockGitHub для своих тестов:

public class MockGitHub implements GitHub {
    private final BehaviorDelegate<GitHub> delegate;
    private final Map<String, Map<String, List<Contributor>>> ownerRepoContributors;

    public MockGitHub(BehaviorDelegate<GitHub> delegate) {
        this.delegate = delegate;
        ownerRepoContributors = new LinkedHashMap<>();

        // Seed some mock data.
        addContributor("square", "retrofit", "John Doe", 12);
        addContributor("square", "retrofit", "Bob Smith", 2);
        addContributor("square", "retrofit", "Big Bird", 40);
        addContributor("square", "picasso", "Proposition Joe", 39);
        addContributor("square", "picasso", "Keiser Soze", 152);
    }

    @Override public Call<List<Contributor>> contributors(String owner, String repo) {
        List<Contributor> response = Collections.emptyList();
        Map<String, List<Contributor>> repoContributors = ownerRepoContributors.get(owner);
        if (repoContributors != null) {
            List<Contributor> contributors = repoContributors.get(repo);
            if (contributors != null) {
                response = contributors;
            }
        }
        return delegate.returningResponse(response).contributors(owner, repo);
    }
}

Затем вы можете использовать MockGitHub в своих тестах, чтобы имитировать виды ответов, которые вы ищете. Полный пример см. В реализациях SimpleService и SimpleMockService для этого Пример перестройки.

Сказав все это, если вы абсолютно должны подключиться к фактическому серверу, вы можете установить Retrofit для синхронного взаимодействия с пользовательским ImmediateExecutor:

public class ImmediateExecutor implements Executor {
    @Override public void execute(Runnable command) {
        command.run();
    }
}

Затем примените его к OkHttpClient, который вы используете при создании Retrofit:

OkHttpClient client = OkHttpClient.Builder()
        .dispatcher(new Dispatcher(new ImmediateExecutor()))
        .build();

Retrofit retrofit = new Retrofit.Builder()
        .client(client)
        //Your params
        .build();

Ответ 3

Если вы не тестируете API-интерфейс QA-сервера, это плохая идея по нескольким причинам.

  • Во-первых, вы заполняете свою производственную базу плохими/поддельными данные
  • Использование ресурсов сервера, когда они могут лучше использоваться для обслуживания действительный запрос

Лучший способ использовать Mockito, или Mock ваши ответы

Кроме того, если вы должны протестировать свой производственный API, протестируйте его один раз и добавьте аннотацию @Ignore. Таким образом, они не запускаются все время и не спамают ваш сервер поддельными данными, и вы можете использовать его всякий раз, когда вы чувствуете, что api не ведет себя правильно.