LoginSignup
21

More than 5 years have passed since last update.

OkHttpのMockWebServerをJUnitで利用する

Last updated at Posted at 2015-11-03

About

JavaでHTTPクライアントのテストを書こうとしていたら、okhttp/mockwebserverなるものを見つけたのですが、これが便利だったので紹介します。

サンプルコードの一部は、GitHubにあります。

題材

RestAPIクライアントの実装にRetrofitを利用する状況を想定し、サンプル題材としてGitHub APIにアクセスするクライアントを考えます。

GitHubService.java
public interface GitHubService {
    /**
     * 指定されたユーザのリポジトリリストを取得.
     * 
     * @param user
     * @reeturn Call<List<Repository>>
     */
    @GET("/users/{user}/repos")
    Call<List<Repository>> listRepos(@Path("user") String user);
}

GitHubServiceの使い方としては、次のようなコードになると思います。
当然ですが、本物のGitHub APIのURLをRetrofitのbaseUrlに設定します。

final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
final GitHubService service = retrofit.create(GitHubService.class);
final Call<List<Repository>> listRepos = service.listRepos("hosopy");

listRepos.enqueue(new Callback<List<Repository>>() {
    @Override
    public void onResponse(Response<List<Repository>> response, Retrofit retrofit) {
    }

    @Override
    public void onFailure(Throwable throwable) {
    }
});

GitHubServiceをテストする

JUnitでGitHubServiceのテストを書きたいとします。

テストなので、本物のGitHub APIにアクセスさせることは避けたいのですが、MockWebServerを利用することで、Webサーバのモックを用意することが出来ます。

MockWebServerを利用して、GitHubServiceをテストするコードはこのように書くことが出来ます。
(Matcherにhamcrest-allを使っています)

GitHubServiceTest.java
@RunWith(JUnit4.class)
public class GitHubServiceTest extends TestCase {

    private static final int TIMEOUT = 10000;

    @Test(timeout = TIMEOUT)
    public void testListReposSuccess() throws IOException, InterruptedException {
        final BlockingQueue<String> events = new LinkedBlockingQueue();

        // MockWebServerとMockResponseを設定
        final MockWebServer mockWebServer = new MockWebServer();
        final MockResponse mockResponse = new MockResponse()
                .setResponseCode(200)
                .setHeader("Content-Type", "application/json")
                .setBody("[{\"name\":\"Bolts-iOS-Sample\", \"html_url\":\"https://github.com/hosopy/Bolts-iOS-Sample\"}," +
                        "{\"name\":\"dotfiles\",\"html_url\":\"https://github.com/hosopy/dotfiles\"}]");
        mockWebServer.enqueue(mockResponse);
        mockWebServer.start();

        // baseUrlにMockWebServerのURLを設定
        final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(mockWebServer.url("/").toString())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        final GitHubService service = retrofit.create(GitHubService.class);
        final Call<List<Repository>> listRepos = service.listRepos("hosopy");

        // テスト
        listRepos.enqueue(new Callback<List<Repository>>() {
            @Override
            public void onResponse(Response<List<Repository>> response, Retrofit retrofit) {
                for (Repository repository : response.body()) {
                    events.offer(repository.getName());
                    events.offer(repository.getHtmlUrl());
                }
            }

            @Override
            public void onFailure(Throwable throwable) {
            }
        });

        assertThat(events.take(), is("Bolts-iOS-Sample"));
        assertThat(events.take(), is("https://github.com/hosopy/Bolts-iOS-Sample"));
        assertThat(events.take(), is("dotfiles"));
        assertThat(events.take(), is("https://github.com/hosopy/dotfiles"));

        mockWebServer.shutdown();
    }
}

MockWebServerは他にも色々な使い方が出来るようなので、GitHubのドキュメントを参照してみて下さい。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21