MockWebServerを使ってAndroid通信をテストする - Re.Ra.Ku アドベントカレンダー day 16
Re.Ra.Ku アドベントカレンダー 16日目です。
こんにちは、安部です。
MockWebServerを使うと通信部分のモックが簡単にできるので、使い方を紹介したいと思います。
okhttp/mockwebserver at master · square/okhttp
(試してませんが、Android以外のJavaプロジェクトでも使えると思います。)
セットアップ
build.gradleに追加します。今回サンプルで使うOkHttpとRetrofitも追加してます。
testCompile 'com.squareup.okhttp3:mockwebserver:3.4.1' compile 'com.squareup.okhttp3:okhttp:3.4.1' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0'
OkHttp
OkHttpを使った通信のテストのサンプルです。
テスト対象コード
URLをもらって通信して結果を返却するだけのコードです。実践的ではないですが、使い方をわかりやすくするために単純にしています。
モックのURLを渡せるようにエンドポイントのURLはコンストラクタで設定しています。
public class Connection { private String baseURL; public Connection(String baseURL) { this.baseURL = baseURL; } public String run() throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(baseURL + "test").build(); Response response = client.newCall(request).execute(); return response.body().string(); } }
テストコード
簡単なテストコードです。
基本的な使い方はレスポンスを設定して、URLを取得して、そこにアクセスする感じです。
public class ConnectionTest { private MockWebServer server; @After public void tearDown() throws Exception { if (server != null) { // モックサーバーを停止 server.shutdown(); } } @Test public void run() throws Exception { server = new MockWebServer(); // レスポンスで返したいものを設定 MockResponse response = new MockResponse() // header .addHeader("Content-Type", "text/plain") // status code .setResponseCode(200) // body .setBody("レスポンス"); server.enqueue(response); // モックサーバーのURL設定と取得 HttpUrl url = server.url("/"); // 実行 Connection connection = new Connection(url.toString()); String result = connection.run(); // レスポンスを確認 assertThat(result, is("レスポンス")); // リクエストを確認 RecordedRequest request = server.takeRequest(); assertThat(request.getPath(), is("/test")); } }
Retrofit + RxJava
RetrofitとRxJavaを使ったサンプルです。
テスト対象コード
想定として、GitHubのユーザー情報を取得する感じのものです。
RxJavaのObservableを返す形になっています。使う側は取得したObservableをsubscribeする感じになるかと思います。
public interface GitHubService { @GET("users/{user}") Observable<User> getUser(@Path("user") String user); }
public class GitHubAPI { private String baseURL; public GitHubAPI(String baseURL) { this.baseURL = baseURL; } public Observable<User> getUser(String user) { Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseURL) // Gson .addConverterFactory(GsonConverterFactory.create()) // RxJava Adapter .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); GitHubService service = retrofit.create(GitHubService.class); return service.getUser(user); } }
public class User { public String id; public String name; }
テストコード
MockWebServerを作るあたりは先程の例と変わりませんが、Observableをテストする方法として、TestSubscriber
を使っています。TestSubscriber
を使うとだいぶテストが書きやすくなると思います。
public class GitHubAPITest { private MockWebServer server; @After public void tearDown() throws Exception { if (server != null) { // モックサーバーを停止 server.shutdown(); } } @Test public void getUser() throws Exception { server = new MockWebServer(); MockResponse response = new MockResponse() .addHeader("Content-Type", "application/json") .setResponseCode(200) .setBody("{\"id\":123456,\"name\":\"Kenji Abe\"}"); server.enqueue(response); HttpUrl url = server.url("/"); GitHubAPI api = new GitHubAPI(url.toString()); // Test用のSubscriber TestSubscriber<User> testSubscriber = TestSubscriber.create(); api.getUser("STAR-ZERO").subscribe(testSubscriber); // 終了するまで待つ testSubscriber.awaitTerminalEvent(); // 完了を確認 testSubscriber.assertCompleted(); // onNextにあたるイベントからデータ取得 User user = testSubscriber.getOnNextEvents().get(0); assertThat(user.id, is(123456)); assertThat(user.name, is("Kenji Abe")); // リクエストを確認 RecordedRequest request = server.takeRequest(); assertThat(request.getPath(), is("/users/STAR-ZERO")); } }
まとめ
MockWebServerを使うことで通信部分のテストが可能になります。使い方もそこまで難しくはないと思うのでオススメです。