(続)railsでモック使ってみた話
helen.hatenablog.com
一晩でさっくり書いたものの追記、修正。
モック・スタブとは
- 単体テストで必要になるパーツを擬似的に再現する仕組み
使われるところ
- 揃っていないため「本物」でテストできない時
- 状況によって変化するオブジェクトがテスト結果に影響する時
モックとスタブの違い
スタブ
RSpectの2系までは以下のようにスタブを使っていました。
obj.stub(:foo).and_return(15) obj.should_receive(:bar)
3系からはこれらがOld Syntax扱いになり、
動きますがconfigに設定を書かないとwarningが出ます
RSpec4では他のgemに切り出されるかもしれません。
Old syntax - RSpec Mocks - RSpec - Relish
一応構文としては、
オブジェクト.stub(:メソッド ).and_return( 戻り値 )
#オブジェクト.メソッドで戻り値が返される
こんな感じですが今回使わないので放置します
書き直してみる
HogeClassから未実装の外部のクラス(OutClass)のメソッド(find_by_id)を呼ぶため
OutClassをモックにしてfind_by_idを呼べるようにします。
# spec before do @out_class_mock = double("OutClass mock") # モック作成 # OutClass#find_by_idが呼ばれたら@out_class_mockを返す allow(OutClass).to receive(:find_by_id).and_return(@out_class_mock) end let(:hoge){ Hoge.find(1) } it "HogeIDに基づき取得した情報が正しいこと" do # モックが返されているか確認する expect(hoge.find_data(id: 1)).to eq @out_class_mock end # HogeClass def find_data(id:, from: 0, size: 20) @find_data = OutClass.find_by_id(id: id, from: from, size: size) end # OutClass # 外部クラスも用意だけしておく class << self def find_by_id(id:, from: 0, size: 20) end
ここで鬼軍曹のありがたいお言葉が
モックの掟
モックを使ったテストでは、以下の確認が基本要素となる(と自分は思っている)ため、これをクリアすると一通りになるかと。
・呼び出し先が正しいこと -> OK(そもそもモック化したメソッドで無いとこける)
・呼び出す際の引数が正しいこと -> ???
・戻り値の使い方が正しいこと -> OK( .and_return した結果を返していることを検証)
というわけで引数の検証します
引数の検証の仕方
expect(オブジェクト).to receive(メソッド).with(引数).and_return(戻したいオブジェクト、値) # 例:hoge_mock#helloが引数としてworldを受け取ることを検証 # worldを受け取ったらreturn successを返します expect(hoge_mock).to receive(:hello).with('world').and_return("return success")
というわけで引数をテストするspecを追加しました
it "find_by_idを呼び出す際の引数が正しいこと" do expect(OutClass).to receive(:find_by_id) # ここでallowすると不適切な引数でもテスト成功してしまう .with(id: 1, from: 0, size: 20) # withでキーワード引数指定できる .and_return(@out_class_mock) # モックを返します expect(hoge.find_data(id: 1)).to eq @out_class_mock end
ちなみに
@out_class_mock = double("OutClass mock") # モック作成 p @out_class_mock
# 出力するとdoubleで指定したものが表示されます #<Double "OutClass mock">
参考
rspec-mocks (3.3.2)
RSpec Mocks 3.4 - RSpec Mocks - RSpec - Relish
RSpec でテストを作るのに役立つ「モック/スタブ」のシンプルな説明 - 酒と泪とRubyとRailsと
Matching arguments - Setting constraints - RSpec Mocks - RSpec - Relish