ゆうなんとかさんの雑記帳的な。

Twitterで踊ったり音ゲーしたりしてるあの名前がよくわからない人が書いてるらしいよ。

RSpecのスタブとモック

まずはライブラリのクラスに対して使ってみましょう。

module Add
  def add_zero
    self.push 0
  end
end
describe Array do
  before { @a = []; @a.stub!(:length).and_return(20) } #スタブはここで
  subject { @a.extend Add }
  its(:length) { should eq 20 }
  it 'calls #push when #add_zero is called' do
    subject.should_receive(:push).with(0).and_return([0]) #モックここ
    subject.add_zero
  end
end

スタブについて

「スタブ(stub)」とはテストで他の実装に依存しないように使うの代用品で、たいていは一見完成しているように見えるものの中身は定数を返すだけものです。これをうまく使うと上位部品からでもテストしながら作り始めることができる素敵な子なのです。
RSpecでは、

オブジェクト.stub!(:メソッドの名前).and_return(返り値)

とすると、あるオブジェクトのメソッドがとりあえず返す値を設定することができます。ちなみに、すでにそのメソッドが完成していても容赦なく上書きするので、上の例のように空の配列なのにlengthが0ではなく20を返すようにすることもできます*1

モックについて

これはメソッドがちゃんと期待したとおりに呼ばれているかどうか確かめるための仕組みです。
今回は自身に0を突っ込むAdd#add_zeroなる必要性はあまりないメソッドが、pushをちゃんと呼び出しているかどうかを確かめています。

オブジェクト.should_receive(:メソッドの名前).with(引数).and_return(返り値)

どうでもいいけどreceiveとrecieveよく間違えるのなんとかしたい
その結果どうなるかというと、

モックとスタブを使う利点はいっしょに動作する個々のクラスやオブジェクトを(例えばコントローラとモデルおよびビュー)を完全に分離してテストできるという点だ。
それはお互いの役割をより明確にできて、よりシンプルかつ堅牢な設計にできると言うことでもある。

(中略)

とにかくモックやスタブによって自然と設計がよくなると思う。

最後大事。

*1:上のテストがちゃんとグリーンになることは確認済み