RSpec::Mocksが少しだけわかったので、忘れないようにまとめておく
用語
テストダブル | テストコードの中で別のオブジェクトの代役を務めるオブジェクト |
メソッドスタブ | レスポンスを自由に定義できるメソッド |
メッセージエクスペクテーション | コールされることが保証されるメソッドスタブ |
テスト対象コード
class Statement def initialize(customer) @customer = customer end def generate "Statement for #{@customer.name}" end end
RSpec Book P.180より引用
メソッドスタブ
テストコード
describe Statement do it "uses the customer's name in the header" do customer = double('customer') ・・・① customer.stub(:name).and_return('Aslak') ・・・② statement = Statement.new(customer) ・・・③ statement.generate.should =~ /~Statement for Aslak/ ・・・④ end end
RSpec Book P.179より引用
① テストダブルを作成←こいつがCustomerクラスのインスタンスの
代わりをする
② ①で作成したテストダブルにメソッドスタブを追加
→コールすると'Aslak'が返ってくるようなnameメソッドを
customerに追加するイメージ
customer.name
=>'Aslak'
となる
③ 作成したテストダブルを使ってStatementクラスのインスタンスを作成
④ statement.generateを呼ぶと、内部でテストダブルのcustomer.nameが
呼ばれて結果が正しく表示されることを確認する
メソッドスタブを使うメリット
- 上のコードでいうCustomerのようなクラスを作っていなくてもテストが書ける
- StatementクラスのテストがCustomerの実装に依存しなくなる
メッセージエクスペクテーション
テストコード
describe Statement do it "uses the customer's name in the header" do customer = double('customer') customer.should_receive(:name).and_return('Aslak') ・・・この行が変わってる statement = Statement.new(customer) statement.generate.should =~ /~Statement for Aslak/ end end
RSpec Book P.181より引用
メソッドスタブとの違い
customer.nameがコールされないとテストが失敗する
class Statement def initialize(customer) @customer = customer end def generate "Statement for Aslak" end end
となっている場合に、
メソッドスタブ:成功
メッセージエクスペクテーション:失敗