Rails4 rspecによるスタブ、モックを使ったテスト

テストでスタブを使う必要があったので、スタブとモックのメモ。


スタブは、あるオブジェクトのメソッドが呼び出された時に、特定の戻り値を返すようにしたい場合に使う。
モックは、あるオブジェクトのメソッドがある引数で呼ばれたときに、特定の戻り値を返すようにしたい場合に使う。


スタブとモックを設定してみる。
Userクラスにget_age(user_id)という、ユーザーIDを渡すと年齢を返してくれる関数があったとする。


どのユーザーでも常に20を返したいとき、スタブで下記のように書く。

# オブジェクト.stub(:メソッド).and_return(戻り値)
User.stub(:get_age).and_return(20)


ユーザーIDが5のユーザーだけ、常に20を返したいとき、モックで下記のように書く。

# オブジェクト.should_recieve(:メソッド).with(引数).and_return(戻り値)
User.should_recieve(:get_age).with(5).and_return(20)


スタブをテストで使ってみる。
Recordクラスの下記のようなsave_recordという関数があったとする。
Userクラスのget_ageという関数はユーザーの年齢を返すものとし、Recordクラスのageはintegerのみを許可するものとする。

def save_record(user_id)
  begin
    self.transaction do    
      record= self.new
      record.user_id = user_id
      record.age = User.get_age(user_id)

      record.save!
    end
    return true
  rescue
    return false
  end
end

この場合、保存が失敗したときにfalseがちゃんと帰ってくるかテストするのは難しい。
そこで、スタブを使うことにした。
ユーザーIDが1のデータは登録済みであるとする。

it "保存に失敗した場合、falseを返す" do       
  # 年齢を返す関数で文字列「あああ」を返すように細工
  User.stub(:get_age).and_return("あああ")
        
  expect(Record.save_record(1)).to be_false
end

Recordクラスのsave_record内で呼ばれるUserクラスのget_ageが不正な値を返すので、保存に失敗し、falseが返ってきた。


参考:
RSpec でテストを作るのに役立つ「モック/スタブ」のシンプルな説明 - 酒と泪とRubyとRailsと