おおいしつかさ


旅行とバイクとドライブと料理と宇宙が好き。
Ubie Discoveryのプログラマ。
Share:  このエントリーをはてなブックマークに追加

Rspecでコントローラのspecファイルを書く

 Rspecを超いまさらながらやっています。Rspecで一番よくわからないのがMock
とstubで、いまでも両者の違いがよくわかっていないし、mockはあるオブジェクトのフリをする仮想的なオブジェクトで、stubはあるインターフェースを偽装するボックスなのかなあとも考えたりしていますが、はっきりと理解していません。
 今、趣味でとあるwebアプリを作っていて、そのログイン処理の部分の仕様をRspecで書いてみました。

  before(:each) do  
    @user = mock("user")  
  end  

まずはUserモデルのインスタンスのフリをするmockオブジェクトをbeforeで作っておきます。 Rspecの例などを見てみると、そのmockオブジェクトやPersonクラスにとstubを定義したりしていますが、今回のログイン仕様ではUserモデルのインスタンスは作らないので用意していません。
 で、ログインが成功する部分の仕様を書きます。

  it "should log in" do  
    User.should_receive(:authenticate).with("abe@mail.com", "abe_pass").and_return(@user)  
    post "login", {:email => "abe@mail.com", :password => "abe_pass"}  
    response.should be_redirect  
    response.should redirect_to(index_url)  
    assigns[:current_user].should == @user  
  end  

 まずはUserモデルにstubを定義します。それぞれのitブロックの中で、それに関係するstubを宣言するのが、Rspecのやりかたみたいです。before部では全体に関係するようなstubだけを定義するらしい。しかも、そのときはshould_receiveメソッドではなくstub!メソッドを使って、検証はさせないようにするようです(こんな理解でいいのかな?)。
 これで、正当なメールアドレスとパスワードをPOSTメソッドで送ると、indexへリダイレクトされてログイン状態になるという仕様が定義されました。あとはこれを通るようにコードを書くだけです。
 ログインに失敗する部分の仕様は下記のとおり。

  it "shouldn't log in" do  
    User.should_receive(:authenticate).with("itou@mail.com", "invalid_pass").and_return(nil)  
    post "login", {:email => "itou@mail.com", :password => "invalid_pass"}  
    response.should be_success  
    response.should render_template("account/login")  
    assigns[:current_user].should be_nil  
  end