Help us understand the problem. What is going on with this article?

OkHttpのMockWebServerをJUnitで利用する

More than 3 years have passed since last update.

About

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

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

https://github.com/hosopy/OkHttpMockSample

題材

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のドキュメントを参照してみて下さい。

hosopy
glpgs
AIR DesignというB2Bサービスを運営しています。機械学習でデザインを空気のように扱える世界を目指しています。
https://www.glpgs.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away