29 Mar 2014, 13:45

RSpecのモックについて調べてみた

今日は、RSpecにおけるモックオブジェクト技法について調べてみました。

モックオブジェクト技法とは

モックオブジェクト技法とは、

  • オブジェクト同士のコラボレーションに注目したテスト方法。
  • オブジェクトの状態よりも、オブジェクト同士のやりとりに注目する。
  • インターフェースのテスト、シーケンス図のテストに注力した技法。

詳しくは、この本がいい。

RSpecにおけるテストダブル

基本は以下。double()メソッドでテストダブルオブジェクトを生成。

テストダブルとは、本物のオブジェクトの代役をするオブジェクト。 映画の俳優のスタントマン。

大抵の場合は、テスト対象のオブジェクトの引数としてオブジェクトが渡される。


   real_foo = Foo.new
   double_foo = double('foo')

   # real_fooをつかわないで、double_fooを渡す
   hoge = Hoge.new(double_foo)

記法には2種類ある。

  • should記法 should_recieve …
  • expect記法 allow/expect

expect記法の方が、より英語らしく感じる。文脈に応じて使い分ける。

スタブ

<div class="outline-text-3" id="text-2-1">
  <p>
    スタブメソッドを指定すると、 テストダブルオブジェクトのメソッドから好きな値を戻り値として得ることができる。
  </p>

  <pre><code>

allow(double_foo).to receive(:call).and_return(“Hello”) double_foo.stub(:call).and_return(“Hello”)

モック

<div class="outline-text-3" id="text-2-2">
  <p>
    スタブに検証機能をつけたものをモックという。検証機能とは、
  </p>

  <ul class="org-ul">
    <li>
      期待された引数で呼ばれたか?
    </li>
    <li>
      期待された回数呼ばれたか?
    </li>
    <li>
      期待された順番で呼ばれたか?
    </li>
  </ul>

  <p>
    などなどを検証する。この機能が、モックオブジェクト技法。 オブジェクト同士のやりとりに注力したテストがかける。
  </p>

  <p>
    期待された値で呼ばれたかは、with()メソッドで検証する。
  </p>

  <pre><code>

expect(double_foo).to recieve(:call).and_return(“Hello”) double_foo.should_recieve(:call).and_return(“Hello”)

リファレンスとか

<div class="outline-text-3" id="text-2-3">
  <p>
    機能が細かいので、詳しくは以下のリンクを参照。
  </p>

  <ul class="org-ul">
    <li>
      <a href="https://relishapp.com/rspec/rspec-mocks/v/3-0/docs">RSpec Mocks 3.0 &#8211; RSpec Mocks &#8211; RSpec &#8211; Relish</a>
    </li>
  </ul>

  <p>
    自分は、この書籍を見ながら勉強している。
  </p>

  <div class='amazlink-box' style='text-align:left;padding-bottom:20px;font-size:small;/zoom: 1;overflow: hidden;'>
    <div class='amazlink-list' style='clear: both;'>
      <div class='amazlink-image' style='float:left;margin:0px 12px 1px 0px;'>
        <a href='http://www.amazon.co.jp/RSpec-Book-Professional-Ruby-Series/dp/4798121932%3FSubscriptionId%3DAKIAJDINZW45GEGLXQQQ%26tag%3Dsleephacker-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798121932' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51-3T735zLL._SL160_.jpg' style='border: none;' /></a>
      </div>

      <div class='amazlink-info' style='height:160; margin-bottom: 10px'>
        <div class='amazlink-name' style='margin-bottom:10px;line-height:120%'>
          <a href='http://www.amazon.co.jp/RSpec-Book-Professional-Ruby-Series/dp/4798121932%3FSubscriptionId%3DAKIAJDINZW45GEGLXQQQ%26tag%3Dsleephacker-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798121932' rel='nofollow' target='_blank'>The RSpec Book (Professional Ruby Series)</a>
        </div>

        <div class='amazlink-powered' style='font-size:80%;margin-top:5px;line-height:120%'>
          posted with <a href='http://amazlink.keizoku.com/' title='アマゾンアフィリエイトリンク作成ツール' target='_blank'>amazlink</a> at 14.03.29
        </div>

        <div class='amazlink-detail'>
          David Chelimsky
        </div>

        <div class='amazlink-sub-info' style='float: left;'>
          <div class='amazlink-link' style='margin-top: 5px'>
            <img src='http://amazlink.fuyu.gs/icon_amazon.png' width='18' /><a href='http://www.amazon.co.jp/RSpec-Book-Professional-Ruby-Series/dp/4798121932%3FSubscriptionId%3DAKIAJDINZW45GEGLXQQQ%26tag%3Dsleephacker-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798121932' rel='nofollow' target='_blank'>Amazon</a>
          </div>
        </div>
      </div>
    </div>
  </div>
</div></p>

実装例

以前書いたステートパターンの実装に対してテストコードを書いてみました。

その他所感

<div class="outline-text-2" id="text-4">
  <p>
    Mock系のツールは、GoogleMockとJMockをつかったことがあるけれども、 RSpecの記法はとてもシンプルなので、気に入った。
  </p>

  <p>
    JavaやC++だと、いちいちインタフェースを定義しないといけない。
  </p>

  <p>
    Rubyでは、それがないの
  </p></p>
</div></p>