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

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

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

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

詳しくは、GOOS本がいい。

RSpecにおけるテストダブル

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

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

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


   real\_foo = Foo.new
   double\_foo = double('foo')

   hoge = Hoge.new(double\_foo)

記法には2種類ある。

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

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

スタブ

スタブメソッドを指定すると、テストダブルオブジェクトのメソッドから好きな値を戻り値として得ることができる。

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

モック

スタブに検証機能をつけたものをモックという。検証機能とは、

  • 期待された引数で呼ばれたか?
  • 期待された回数呼ばれたか?
  • 期待された順番で呼ばれたか?

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

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


   expect(double\_foo).to recieve(:call).and\_return("Hello")
   double\_foo.should\_recieve(:call).and\_return("Hello")

リファレンスとか

機能が細かいので、詳しくは以下のリンクを参照。

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

実装例

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

https://gist.github.com/tsu-nera/9853933

その他所感

Mock系のツールは、GoogleMockとJMockをつかったことがあるけれども、 RSpecの記法はとてもシンプルなので、気に入った。

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

Rubyでは、それがないのが素敵だ。