-
Rspecでコントローラのspecファイルを書く 2007-11-10 00:00:00
Rspecを超いまさらながらやっています。Rspecで一番よくわからないのがMoc
k と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 -
Rspecではそれぞれの検証が分離している 2007-11-10 00:00:00
言葉にすると至極あたりまえの話のような気もしますが、Rspecでは、モデルとコントローラとビューのテストはそれぞれ分離されています(Rspecでも、should have_tagでビューの検証ができてしまいますが、結合度が密になりやすそうなのであまり使わないほうがいいかもです)。結合度を疎にすることによって、コントローラの仕様を考えるときはそれに専念することができます。そして、どこかのエラーが他に影響を及ぼすのを防いでいます。例えば、ビューの仕様を変更してエラーが出たとき、そのビューの仕様をコントローラに書いているとコントローラでもエラーが出る(当たり前すぎることを書いていますね)のです。
とはいえ、Test::Unitのfunctionテストとかだと、結構普通にコントローラとビューのテストを一緒に書いちゃってます。def test_diary get "diary", {:id => diaries(:abe_1).id} assert_response :success assert_template "diary/show" assert_select "#diary_#{diaries(:abe_1).id}" do assert_select "#title", diaries(:abe_1).title assert_select "#body", diaries(:abe_1).body end endここでデザイナさんが、日記の内容のIDを"#message"に変えたりすると、このテストはエラーになってしまいます。しかし、コントローラがおかしくてエラーになるわけではないのです。
さらにいうと、ここでDiaryモデルがid値からインスタンスを取得する部分の仕様を変えたときに、エラーになる可能性があります。
ここで疎結合を保つために登場するのがmockとstubなのですね。なるほど。

コメント(
リンク元(256)