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);
}
偽の応答をすることはできますが、実際にテストする必要があります。成功ですか?体は正しいですか?コードを手伝ってもらえますか?
答えは思ったよりも簡単です:
CountDownLatchを使用すると、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;
}}
通常、実サーバーの要求をテストすることはお勧めできません。このトピックに関する興味深い議論については、 このブログ投稿 を参照してください。著者によると、実際のサーバーを使用することは問題です:
- 断続的に故障する可能性のある別の可動部品
- 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応答をシミュレートできます。 here を使用する方法の例を参照してください。
最後に、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
と同期して動作するようにRetrofitを設定できます。
public class ImmediateExecutor implements Executor {
@Override public void execute(Runnable command) {
command.run();
}
}
次に、レトロフィットを作成するときに使用するOkHttpClient
に適用します。
OkHttpClient client = OkHttpClient.Builder()
.dispatcher(new Dispatcher(new ImmediateExecutor()))
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
//Your params
.build();
QAサーバーAPIをテストしているのでなければ、いくつかの理由で悪い考えです。
Mockitoを使用する最良の方法、または応答をモックする
また、実稼働APIをテストする必要がある場合は、一度テストして@Ignoreアノテーションを追加します。そうすれば、それらは常に実行されるわけではなく、偽のデータでサーバーをスパムすることもありません。また、APIが正しく動作していないと感じるときはいつでも使用できます。