Test urządzenia Android z Retrofit2 i Mockito lub Robolectric

Czy Mogę przetestować realną odpowiedź z retrofit2beta4? Potrzebuję Mockito czy Robolectic?

Nie mam działań w moim projekcie, będzie to biblioteka i muszę przetestować czy serwer reaguje poprawnie. Teraz mam taki kod i utknąłem...

@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);
}
Mogę zrobić fałszywą odpowiedź, ale muszę przetestować prawdziwą. Czy to sukces? Czy ciało jest prawidłowe? Pomożesz mi z kodem?
Author: AndrewS, 2016-03-02

3 answers

Ogólnie nie jest dobrym pomysłem testowanie prawdziwych żądań serwera. Zobacz ten wpis na blogu {[15] } dla ciekawej dyskusji na ten temat. Według autora korzystanie z prawdziwego serwera jest problemem, ponieważ:

  • kolejny ruchomy element, który może zawieść sporadycznie
  • Aby wdrożyć serwer i aktualizować go, konieczne jest posiadanie specjalistycznej wiedzy poza domeną Androida]}
  • trudne do wywołania przypadki błędów / krawędzi
  • powolne wykonywanie testów (wciąż wykonywanie połączeń HTTP)

Możesz uniknąć wszystkich powyższych problemów, używając serwera makietowego, takiego jak serwer OkHttp MockWebServer do symulacji rzeczywistych wyników odpowiedzi. Na przykład:

@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();
}
Jeśli chcesz symulować opóźnienia sieciowe, możesz dostosować swoją odpowiedź w następujący sposób:]}
MockResponse response = new MockResponse()
    .addHeader("Content-Type", "application/json; charset=utf-8")
    .addHeader("Cache-Control", "no-cache")
    .setBody("{}");
response.throttleBody(1024, 1, TimeUnit.SECONDS);

Alternatywnie, możesz użyć MockRetrofit i NetworkBehavior do symulacji odpowiedzi API. Zobacz tutaj przykład jak z niego korzystać.

Wreszcie, jeśli chcesz tylko przetestować swój Usługa modernizacji, najłatwiej byłoby stworzyć jego wersję próbną, która emituje wyniki próbne dla testów. Na przykład, jeśli masz następujący interfejs usługi GitHub:

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

Możesz następnie utworzyć następujące MockGitHub dla swoich testów:

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);
    }
}

Możesz następnie użyć MockGitHub w swoich testach, aby symulować rodzaje odpowiedzi, których szukasz. Aby uzyskać pełny przykład, zobacz implementacje SimpleService i SimpleMockService dla tego przykład modernizacji .

Powiedziawszy to wszystko, jeśli koniecznie musisz połączyć się z rzeczywistym serwerem, możesz ustawić Retrofit tak, aby działał synchronicznie z niestandardowym ImmediateExecutor:

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

Następnie zastosuj go do OkHttpClient, którego używasz podczas budowania modernizacji:

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

Retrofit retrofit = new Retrofit.Builder()
        .client(client)
        //Your params
        .build();
 92
Author: Ricardo Lage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-12 07:45:50

Odpowiedź jest zbyt łatwa, niż się spodziewałem:

Użycie CountDownLatch sprawia, że twój test czeka na wywołanie countDown ()

public class SimpleRetrofitTest {

private static final String login = "your@login";
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;
}}
 15
Author: AndrewS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-08 12:05:53

Jeśli nie testujesz QA server API, jest to zły pomysł z kilku powodów.

  • Po pierwsze wypełniasz swoją bazę danych produkcji złym / fałszywym dane
  • Korzystanie z zasobów serwera, gdy mogą lepiej służyć valid request

The best way to use Mockito, or Mock your responses

Jeśli musisz przetestować swoje API produkcyjne, przetestuj je raz i dodaj adnotację @ Ignore. W ten sposób nie są one uruchamiane przez cały czas i nie spamuj serwera fałszywymi danymi możesz go używać, gdy uważasz, że api nie działa poprawnie.

 -2
Author: Akshay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-04 00:28:00