railsでモック使ってみた話
開発チームで
railsでモックの調査する人柱になってくれる人!という募集があり
人柱やりまーすと立候補したところから始まりました。
実は一回挫折していて気になっていたのと
ちょうど自分の作業に区切りがついたのでやってみました
使い方
モックが呼び出せるメソッドの設定
allow(モックオブジェクト).to receive(メソッド名)
オブジェクトの置き換え方
allow(実装を置き換えたいオブジェクト).to receive(置き換えたいメソッド名).and_return(返却したい値やオブジェクト)
実装例
例)商品に基づいてメーカーを取得する
spec
describe "商品に紐付いたメーカーを取得します" do before do # double()でモックを作ります # 文字列は省略可ですが、この文字列はテスト失敗時に表示されます maker_mock = double('maker mock test') # maker_mockがfind_with_itemsメソッドを呼び出せるようにします allow(maker_mock).to receive(:find_with_items) @makers = Makers.new # オブジェクトが呼ばれたらモックに置き換える allow(@makers).to receive(:find_with_items).and_return(maker_mock) # これでmaker_mockはfind_with_itemsを呼び出せるようになり # @makersでmaker_mockが呼ばれる end context "正常系" do it "取得した商品のメーカーが存在すること" do expect(@maker.find_with_items).to be_present end end end
model
class Makers < ActiveRecord::Base def find_with_items maker.all end end
実行結果
# テスト成功例 $ bundle exec rspec spec/models/makers_spec.rb . Finished in 0.02464 seconds (files took 1.97 seconds to load) 1 example, 0 failures # テスト失敗例 $ bundle exec rspec spec/models/makers_spec.rb F Failures: 1) 商品に紐付いたメーカーを取得します 正常系 取得した商品のメーカーが存在すること Failure/Error: expect(@makers.find_with_itemss).to be_present # ここにdouble()で入れた文字列が表示されます expected `#<Double "maker mock test">.present?` to return false, got true # ./spec/models/makers_spec.rb:27:in `block (4 levels) in <top (required)>' Finished in 0.02958 seconds (files took 1.9 seconds to load) 1 example, 1 failure
モックのメソッドが呼ばれているか検証する
expect(モックオブジェクト).to receive(メソッド名)
expectの場合はそのメソッドが呼ばれないとテスト失敗になります。
before do maker_mock = double('maker mock test') # maker_mockがfind_with_itemsメソッドを呼び出せるようにします allow(maker_mock).to receive(:find_with_items) @makers = Makers.new # 変更点:allowをexpectにします expect(@makers).to receive(:find_with_items).and_return(makers_mock) end
実装を置き換えるのか、メソッドの呼び出しも検証するのかでallowとexpectを使い分けます。
今まとめてて思ったけどちょっといろいろ怪しいんで
出社したらプルリクWIPにして再調査しようかなというところです...
うーん、難しい
参考
Ruby - 使えるRSpec入門・その3「ゼロからわかるモック(mock)を使ったテストの書き方」 - Qiita
Expecting messages - Basics - RSpec Mocks - RSpec - Relish
Rspec3のexpectとallowの違い - JanGaJan.com