SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

オイシックスの事例から学ぶ、JavaのWebアプリに自動テストを導入する方法

Javaのモックアップフレームワーク「mockito」でリクエスト/セッションを再現する

オイシックスの事例から学ぶ、JavaのWebアプリに自動テストを導入する方法 第3回

  • X ポスト
  • このエントリーをはてなブックマークに追加

Cartクラスでのモック使用例

 Cartクラスは、ショッピングサイトなどでお客様のカート情報を管理するクラスです。

 このクラスのadd(Shouhin shouhin, int num)メソッドは、引数で渡された商品をカートに入れるクラスになります。引数で渡しているShouhinクラスは、Hibernateのモデルクラスになります。まずは、以下のソースをざっと読んでみてください。

Cart.class
public class Cart {

    public int add(Shouhin shouhin, int num) {
        ・
        ・
        ・
        if (!canBuy(shouhin)) {
            return CANNOT_BUY;
        } else {
            return ADD_OK;
        }
        ・
        ・
        ・
    }

    private boolean canBuy(Shouhin shouhin) {
        int status = shouhin.inquireStatus();  // DB問い合わせ
        if (status == Shouhin.STATUS_SOLD_TO_END ||  // 終売
            status == Shouhin.STATUS_SOLD_OUT) {  // 売切
            return false;
            } else if (status == Shouhin.LIMITED_NUM) {  // 数量限定
            ・
            ・
            ・
            // 買える個数であればtrue
            ・
            ・
        } else {
            return true;  // 購入可能
        }
    }

}

 このメソッドの18行目にあるshouhin.inquireStatus()では、商品のステータスをデータベースに問い合わせます。単純にフィールド値を返すのではなく、DBアクセスをしてステータスを取得するメソッドです。Cartクラスのadd(Shouhin shouhin, int num)メソッドのユニットテストを書くのであれば、次の4パターンの商品状態をデータベースに作る必要があります。

  1. 終売
  2. 売切
  3. 数量限定
  4. 購入可能

 ユニットテストとしては、CartクラスのテストなのでShouhinクラスのDBアクセスまで検証する必要はありませんが、テストには必要なのでデータベースにその状態を作らなければなりません。データベースのレコード作成は、非常にシンプルなテーブルであれば、さほど手間も時間も掛からないでしょう。しかし、商品のような付随情報が多いテーブルとなると、関わるテーブルも多くなり、想像しているよりも沢山のデータを作る必要があります。このような場合に、モックが役に立つのです。以下がmockitoを使って書いたテストケースです。

テストコード
// 終売
Shouhin shouhinMock = mock(Shouhin.class);
when(shouhinMock.inquireStatus()).thenReturn(Shouhin.STATUS_SOLD_TO_END);
assertThat(cart.add(shouhinMock, 1), is(Cart.CANNOT_BUY));

// 売切
shouhinMock = mock(Shouhin.class);
when(shouhinMock.inquireStatus()).thenReturn(Shouhin.STATUS_SOLD_OUT);
assertThat(cart.add(shouhinMock, 1), is(Cart.CANNOT_BUY));

// 数量限定
shouhinMock = mock(Shouhin.class);
when(shouhinMock.inquireStatus()).thenReturn(Shouhin.STATUS_SOLD_OUT);
assertThat(cart.add(shouhinMock, 1), is(Cart.ADD_OK));

// 購入可能
shouhinMock = mock(Shouhin.class);
when(shouhinMock.inquireStatus()).thenReturn(Shouhin.CAN_BUY);
assertThat(cart.add(shouhinMock, 1), is(Cart.ADD_OK));

 「// 終売」のテストコードを例に、コードを説明します。

 まず1行目の以下文でShouhinクラスのモックを作っています。

Shouhin shouhinMock = mock(Shouhin.class);

 この1行だけで、Shouhinクラスのモックを簡単に作ることができます。

補足

 mock()メソッドはMockitoクラスのstaticメソッドではありますが、static importをしているため、このような書き方が可能です。

 続いて2行目です。こちらではinquireStatus()メソッドをモック化しています。

when(shouhinMock.inquireStatus()).thenReturn(Shouhin.STATUS_SOLD_TO_END);

 when()メソッドもMockitoクラスのstaticメソッドで、static importをしているため、このような書き方ができます。

when(①xxxxxxxxxx).thenReturn(②xxxxxxxxxx); 

 この文を見て、何か気づくことはないでしょうか?

 JUnitはテストケースを自然言語(普通の英文)のように読めるように工夫されています。mockitoも同じ思想のようで、「①xxxxxxxxxxの場合(時)は、②xxxxxxxxxxをリターンします」と訳せると思います。直感的に読むことができて理解しやすいです。

 このことが分かっていれば、プログラムは容易に理解できるのではないでしょうか。引数には、戻り値を指定したいmethodCall: shouhinMock.inquireStatus()を指定します。そしてthenReturnには、メソッドの戻り値: Shouhin.STATUS_SOLD_TO_ENDを指定します。これでメソッドをモック化することができました。

 このようにモック化したinquireStatus()を呼ぶと、Shouhin.STATUS_SOLD_TO_ENDが返るようになります。3行目はassertThat()でcart.add()の検証をしています。こちらについては、基本的なJUnitの知識があることを前提としていますので、本稿での詳しい説明は割愛します。

assertThat(cart.add(shouhinMock, 1), is(Cart.CANNOT_BUY));

 例では、実際にmockitoを使用しているテストコードの説明をしました。mockitoを使い、Shouhinクラスのモックを作ることにより、このように複数のパターンのテストコードを簡単に記述できます。このやり方であれば、データベースに状態を作る必要もないので、手間と時間が掛からず効率も良いと思います。

補足

 もちろんShouhinクラスのユニットテストで、データベースに状態を作ってのテストをする必要はあります。

次のページ
mockitoでリクエスト/セッションを再現

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
オイシックスの事例から学ぶ、JavaのWebアプリに自動テストを導入する方法連載記事一覧

もっと読む

この記事の著者

山田 昌平(オイシックス株式会社)(ヤマダ ショウヘイ)

オイシックスでは 運用→開発→開発推進を担当してきました。あと、ITイベントの協賛も担当しております。イベントは、技術的な面、エンジニアとしての考え方など、本当に学ぶことが多いのでおすすめです。お会いすることもあると思いますので気軽に声をお掛けください。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7719 2014/04/14 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング