15 Jun 2012

ひとりごと on RSpec

ああ かれこれ1時間くらい CapybaraのRSpec上でActioveRecord::Baseなクラスの値がchangeしないパターンにはまってた。

こんな場合;
ユーザのパスワードリセッタを実装するときにone_time_tokenを発行してメールを送信する。メール中のtokenとデータベイスに保存されたtokenが一緒かチェック。同じだったら、パスワードを再設定する画面に進む。他にもセキュリティを守るための処理はあるけど基本的な処理はそんなかんじ。

Specはこんな感じ
let(:user) { User.make } # => machinist/acive_record

 it "user's token should be updated" do
  expect{ click_button 'メール送信' }.to change{ user.one_time_token }
end

expect{ click_button 'メール送信'; user.reload }.to change{ user.one_time_token }
# => Got: one_time_token is still ""


正しくはuser.reloadを追加しないといけない。
it "user's token should be updated" do
  expect{ click_button 'メール送信'; user.reload }.to change{ user.one_time_token }
end

changeの中は遅延評価されたuser を参照しているからRSpecの空間で故意にreloadしないと one_time_tokenがActiveRecord上では変わらない。普通の人はすぐ気づくのかなあ?