2011-09-16 10 views
55

current_userメソッドのレスポンスをRspec/capybaraリクエスト仕様でスタブする必要があります。このメソッドはApplicationControllerで定義されており、helper_methodを使用しています。メソッドは単純にユーザーIDを返す必要があります。テストでは、このメソッドが毎回同じユーザーIDを返すようにしたいと思います。リクエスト仕様のApplicationControllerメソッドをスタブする方法

また、session[:user_id]を仕様(これはcurrent_userが返すものです)に設定することで問題を解決することもできますが、それでも問題はありません。

いずれか可能ですか?

編集:ここでは

は(それが機能していないそれはちょうど、通常のCURRENT_USERメソッドを実行します。)私が持っているものです。また、機能していない

require 'spec_helper' 

describe "Login" do 

    before(:each) do 
    ApplicationController.stub(:current_user).and_return(User.first) 
    end 

    it "logs in" do 
    visit '/' 
    page.should have_content("Hey there user!") 
    end 

end 

require 'spec_helper' 

describe "Login" do 

    before(:each) do 
    @mock_controller = mock("ApplicationController") 
    @mock_controller.stub(:current_user).and_return(User.first) 
    end 

    it "logs in" do 
    visit '/' 
    page.should have_content("Hey there user!") 
    end 

end 
+13

で説明したようにビューのメソッドをスタブすることによってこれを解決?私はないと思う。したがって、 'ApplicationController.stub(:current_user)'の代わりに 'ApplicationController.any_instance.stub(:current_user)'が必要な場合があります。 – skalee

答えて

13

をここでは、基本的なフォームの例のカップルです。あなたの特定のケースで

controller.stub(:action_name).and_raise([some error]) 
controller.stub(:action_name).and_return([some value]) 

、私は適切なフォームがあることと考えている:私のフルを説明するために

describe PortalsController do 

    it "if an ActionController::InvalidAuthenticityToken is raised the user should be redirected to login" do 
    controller.stub(:index).and_raise(ActionController::InvalidAuthenticityToken) 
    get :index 
    flash[:notice].should eql("Your session has expired.") 
    response.should redirect_to(portals_path) 
    end 

end 

controller.stub(:current_user).and_return([your user object/id]) 

は、ここで私が上で動作プロジェクトからの完全な作業例ですたとえば、基本的には、ActionController::InvalidAuthenticityTokenエラーがアプリ内のどこにでも発生した場合、フラッシュメッセージが表示され、ユーザはportals_controller#index actioにリダイレクトされることを確認しますn。これらのフォームを使用して、特定の値をスタブアウトして戻したり、特定のエラーのインスタンスをテストしたりすることができます。.stub(:action_name).and_[do_something_interesting]()メソッドがいくつか用意されています。


更新(あなたのコードを追加した後):それは読み込むので、私のコメントごとに、あなたのコードを変更:

require 'spec_helper' 

describe "Login" do 

    before(:each) do 
     @mock_controller = mock("ApplicationController") 
     @mock_controller.stub(:current_user).and_return(User.first) 
    end 

    it "logs in" do 
    visit '/' 
    page.should have_content("Hey there user!") 
    end 

end 
+0

ご回答いただきありがとうございますが、リクエスト仕様ではなくコントローラ仕様のようです。私はかなりテストに新しいので、私は間違っている可能性があります:) –

+0

スタブは、任意のクラスで定義されたメソッドの置換えとして機能します。あなたが与えた例では、 'ApplicationController'で定義された' current_user'メソッドです。正しい?私はあなたの質問を誤解していない限り、同じ基本的なフォームが機能するはずです。あなたが書いたテストの最良の形を、それが動作していなくても投稿できますか? – jefflunt

+0

私はあなたのテストが 'describe ApplicationController'で始まるspecの中にあると仮定していました。そうでない場合は、 'ApplicationController.stub(:current_user).and_return([あなたのユーザオブジェクト/ ID])'を実行できるはずです。 – jefflunt

57

skaleeはコメントで正しい答えを提供しているようです。

あなたがスタブしようとしている方法は、あなたが使用することを必要とするインスタンスメソッド(最も可能性が高い)とないクラスメソッドである場合:

ApplicationController.any_instance.stub(:current_user)

+25

これはRspec 3でも引き続き有効ですが、廃止予定の警告が表示されます。これは新しい構文です: 'allow_any_instance_of(ApplicationController).to receive(:current_user)。and_return(your_test_user) ' – Sharagoz

+1

この引用が大好き - 「この機能はデザインの匂いであることが多い」 - [Rspec docs](https://github.com/rspec/rspec-mocks)。 – brntsllvn

3

これは私のために働いてくれ@current_user変数を与えますテストで使う

私はこのようになりますヘルパーがあります。

def bypass_authentication 
    current_user = FactoryGirl.create(:user) 

    ApplicationController.send(:alias_method, :old_current_user, :current_user) 
    ApplicationController.send(:define_method, :current_user) do 
    current_user 
    end 
    @current_user = current_user 
end 

def restore_authentication 
    ApplicationController.send(:alias_method, :current_user, :old_current_user) 
end 

をそして私の要求の仕様で、私が呼び出す:アプリケーションのコントローラメソッドをスタブする必要があり、たまたま他の誰のために

before(:each){bypass_authentication} 
after(:each){restore_authentication} 
2

なぜなら、あなたがそれをしてはならない理由について無限の怒りに悩まされていたからです。ここでは、Rspecの味わいと一緒に働く方法があります。

before(:each) do 
    campaign = Campaign.create! 
    ApplicationController.any_instance.stub(:load_campaign_singleton) 
    controller.instance_eval{@campaign = campaign} 
    @campaign = campaign 
end 

これは何もしないようにメソッドをスタブし、rspecのコントローラインスタンスにivarを設定し、テストで@campaignとして利用できるようにします。

+0

無限のワクキングを終わらせるためのツールが遅れていますが、私のコンピュータを窓から投げ捨てないように、ちょうどニックネームになっています。ありがとう! – eggmatters

1

私のために提供された回答はありませんでした。 @ matt-fordamのオリジナル記事のように、私は要求仕様を持っていますが、コントローラ仕様はありません。このテストでは、コントローラを起動せずにビューをレンダリングするだけです。

私は `クラスメソッドをcurrent_user`されています。このother SO post

view.stub(:current_user).and_return(etc) 
関連する問題