Kan ik de echte respons van retrofit2beta4 testen? Heb ik Mockito of Robolectica nodig?
Ik heb geen activiteiten in mijn project, het wordt een bibliotheek en ik moet testen of de server correct reageert.
Nu heb ik zo’n code en zit vast…
@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);
}
Ik kan een nepantwoord geven, maar ik moet het echt testen. Is het succes? Is het lichaam correct?
Kun je me helpen met code?
Antwoord 1, autoriteit 100%
Het is over het algemeen geen goed idee om echte serververzoeken te testen. Zie deze blogpostvoor een interessante discussie over het onderwerp. Volgens de auteur is het gebruik van je echte server een probleem omdat:
- Nog een bewegend stuk dat af en toe kan falen
- Vereist enige expertise buiten het Android-domein om de server te implementeren en up-to-date te houden
- Moeilijk om fout-/randgevallen te activeren
- Langzame testuitvoering (maakt nog steeds HTTP-aanroepen)
Je kunt alle bovenstaande problemen vermijden door een nepserver te gebruiken, zoals OkHttp’s MockWebServerom echte responsresultaten te simuleren. Bijvoorbeeld:
@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();
}
Als u netwerkvertragingen moet simuleren, kunt u uw reactie als volgt aanpassen:
MockResponse response = new MockResponse()
.addHeader("Content-Type", "application/json; charset=utf-8")
.addHeader("Cache-Control", "no-cache")
.setBody("{}");
response.throttleBody(1024, 1, TimeUnit.SECONDS);
Als alternatief kunt u MockRetrofit
en NetworkBehavior
gebruiken om API-reacties te simuleren. Zie hiereen voorbeeld van hoe het te gebruiken.
Ten slotte, als u uw Retrofit-service alleen wilt testen, is het het gemakkelijkst om er een nepversie van te maken die nepresultaten voor uw tests afgeeft. Als u bijvoorbeeld de volgende GitHub
-service-interface heeft:
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
Je kunt dan de volgende MockGitHub
maken voor je 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);
}
}
U kunt dan de MockGitHub
gebruiken voor uw tests om het soort reacties te simuleren waarnaar u op zoek bent. Zie voor het volledige voorbeeld de implementaties van de SimpleServiceen SimpleMockServicevoor deze Retrofit-voorbeeld.
Dit alles gezegd hebbende, als u absoluut verbinding moet maken met de eigenlijke server, kunt u Retrofit zo instellen dat het synchroon werkt met een aangepaste ImmediateExecutor
:
public class ImmediateExecutor implements Executor {
@Override public void execute(Runnable command) {
command.run();
}
}
Pas het vervolgens toe op de OkHttpClient
die u gebruikt bij het bouwen van de Retrofit:
OkHttpClient client = OkHttpClient.Builder()
.dispatcher(new Dispatcher(new ImmediateExecutor()))
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
//Your params
.build();
Antwoord 2, autoriteit 16%
Het antwoord is te makkelijk dan ik had verwacht:
Als u CountDownLatch gebruikt, wacht uw test totdat u countDown() aanroept
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;
}}
Antwoord 3
Tenzij u de QA-server-API test, is het om verschillende redenen een slecht idee.
- Ten eerste vult u uw productiedatabase met slecht/nep
gegevens - Serverbronnen gebruiken, wanneer ze beter kunnen worden gebruikt om te dienen
geldig verzoek
De beste manier om Mockito te gebruiken, of uw reacties te bespotten
Als u uw productie-API moet testen, test deze dan een keer en voeg @Ignore-annotatie toe. Op die manier worden ze niet de hele tijd uitgevoerd en spammen ze uw server niet met nepgegevens en kunt u deze gebruiken wanneer u denkt dat de api zich niet correct gedraagt.