Test de l'Unité Android avec Retrofit2 et Mockito ou Robolectric
puis-je tester la réponse réelle de retrofit2beta4? Ai-je besoin de Mockito ou de Robolectic?
Je n'ai pas d'activités dans mon projet, ce sera une bibliothèque et je dois tester si le serveur répond correctement. Maintenant j'ai un tel code et je suis coincé...
@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);
}
je peux faire une fausse réponse, mais je dois tester réel. Est-il le succès? Est-il du corps correcte? Pouvez-vous m'aider avec le code?
3 réponses
ce n'est généralement pas une bonne idée de tester de vraies requêtes de serveur. Voir ce post pour une discussion intéressante sur le sujet. Selon l'auteur, utiliser votre serveur réel est un problème car:
- une Autre pièce qui peut échouer par intermittence
- nécessite une certaine expertise en dehors du domaine Android pour déployer le serveur et le maintenir à jour
- Difficile pour déclencher d'erreur/cas isolés
- exécution de test lente (toujours en train de faire des appels HTTP)
vous pouvez éviter tous les problèmes ci-dessus en utilisant un serveur simulé tel que MockWebServer pour simuler des résultats de réponse réels. Par exemple:
@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();
}
si vous avez besoin de simuler des retards réseau, vous pouvez personnaliser votre réponse comme suit:
MockResponse response = new MockResponse()
.addHeader("Content-Type", "application/json; charset=utf-8")
.addHeader("Cache-Control", "no-cache")
.setBody("{}");
response.throttleBody(1024, 1, TimeUnit.SECONDS);
Alternativement, vous pouvez utiliser MockRetrofit
et NetworkBehavior
pour simuler les réponses API. Voir ici une exemple de comment l'utiliser.
enfin, si vous voulez simplement tester votre service D'adaptation, le plus simple serait de créer une version simulée de celle-ci qui émet des résultats simulés pour vos tests. Par exemple, si vous avez le suivant GitHub
interface de service:
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
vous pouvez alors créer le MockGitHub
pour vos tests:
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);
}
}
vous pouvez alors utiliser le MockGitHub
sur vos tests de simuler les types de réponses que vous cherchez. Pour le plein exemple, voir les implémentations de l' SimpleService et SimpleMockService de cette Rénovation exemple.
ceci étant dit, si vous devez absolument vous connecter au serveur actuel, vous pouvez configurer Retrofit pour fonctionner de manière synchrone avec un
public class ImmediateExecutor implements Executor {
@Override public void execute(Runnable command) {
command.run();
}
}
alors appliquez - le à la OkHttpClient
vous utilisez lors de la construction de la Rénovation:
OkHttpClient client = OkHttpClient.Builder()
.dispatcher(new Dispatcher(new ImmediateExecutor()))
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
//Your params
.build();
La réponse est trop facile que je le pensais:
utiliser CountDownLatch fait attendre votre test jusqu'à ce que vous appeliez 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;
}}
à moins que vous ne testiez L'API QA server, c'est une mauvaise idée pour plusieurs raisons.
- tout D'abord vous peuplez votre base de données de production avec mauvais / faux données
- en utilisant les ressources du serveur, quand elles peuvent être mieux utilisées pour servir demande valide
La meilleure façon d'utiliser Mockito, ou pour se Moquer de vos réponses
aussi, si vous devez tester votre API de production, le tester une fois et ajouter @Ignore annotation. De cette façon, ils ne sont pas tout le temps et ne sont pas spam votre serveur avec de fausses données et vous pouvez l'utiliser chaque fois que vous sentez que l'api ne se comporte pas correctement.