2011-04-26 10 views
76

अनुरोध प्रमाणीकरण में प्रमाणीकरण को दबाते समय, आप सत्र और/या स्टब नियंत्रक विधियों को कैसे सेट करते हैं? मैं अपने एकीकरण परीक्षण में प्रमाणीकरण बाहर ठूंठ कोशिश कर रहा हूँ - rspec/अनुरोध spec

का अनुरोध करता है यहाँ एक परीक्षण का एक उदाहरण है

require File.dirname(__FILE__) + '/../spec_helper' 
require File.dirname(__FILE__) + '/authentication_helpers' 


describe "Messages" do 
    include AuthenticationHelpers 

    describe "GET admin/messages" do 
    before(:each) do 
     @current_user = Factory :super_admin 
     login(@current_user) 
    end 

    it "displays received messages" do 
     sender = Factory :jonas 
     direct_message = Message.new(:sender_id => sender.id, :subject => "Message system.", :content => "content", :receiver_ids => [@current_user.id]) 
     direct_message.save 
     get admin_messages_path 
     response.body.should include(direct_message.subject) 
    end 
    end 
end 

सहायक:

module AuthenticationHelpers 
    def login(user) 
    session[:user_id] = user.id # session is nil 
    #controller.stub!(:current_user).and_return(user) # controller is nil 
    end 
end 

और ApplicationController कि प्रमाणीकरण संभालती है :

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    helper_method :current_user 
    helper_method :logged_in? 

    protected 

    def current_user 
    @current_user ||= User.find(session[:user_id]) if session[:user_id] 
    end 

    def logged_in? 
    !current_user.nil? 
    end 
end 

यह क्यों नहीं है इन संसाधनों तक पहुंचने के लिए खून?

1) Messages GET admin/messages displays received messages 
    Failure/Error: login(@current_user) 
    NoMethodError: 
     undefined method `session' for nil:NilClass 
    # ./spec/requests/authentication_helpers.rb:3:in `login' 
    # ./spec/requests/message_spec.rb:15:in `block (3 levels) in <top (required)>' 

उत्तर

97

एक अनुरोध कल्पना एक पतली आवरण के आसपास ActionDispatch::IntegrationTest, जो नियंत्रक चश्मा तरह काम नहीं करता है (जो चादर ActionController::TestCase)। भले ही एक सत्र विधि उपलब्ध है, मुझे नहीं लगता कि यह समर्थित है (यानी यह शायद वहां है क्योंकि एक मॉड्यूल जो अन्य उपयोगिताओं के लिए शामिल हो जाता है, उस विधि में भी शामिल है)।

मैं उपयोगकर्ताओं को प्रमाणीकृत करने के लिए उपयोग की जाने वाली किसी भी कार्रवाई को पोस्ट करके लॉग इन करने की अनुशंसा करता हूं। आप सभी उपयोगकर्ता कारखानों के लिए पासवर्ड 'पासवर्ड' (उदाहरण के लिए) बनाने हैं, तो आप कुछ इस तरह कर सकते हैं: अगर आप वसीयत का उपयोग कर रहे

 
def login(user) 
    post login_path, :login => user.login, :password => 'password' 
end 
+0

धन्यवाद डेविड। यह बहुत अच्छा काम करता है, लेकिन ऐसा लगता है कि ये सभी अनुरोध करने के लिए थोड़ा अधिक है? –

+17

अगर मैंने सोचा कि यह अधिक था, तो मैंने इसकी सिफारिश नहीं की होगी :) –

+4

यह विश्वसनीय रूप से करने का सबसे आसान तरीका भी है। 'ActionDispatch :: IntegrationTest' को वास्तविक ब्राउज़र का उपयोग किए बिना ब्राउज़र के माध्यम से बातचीत करने वाले एक या अधिक उपयोगकर्ताओं को अनुकरण करने के लिए डिज़ाइन किया गया है। संभावित रूप से एक से अधिक उपयोगकर्ता हैं (यानी।सत्र) और एक उदाहरण के भीतर एक से अधिक नियंत्रक, और सत्र/नियंत्रक ऑब्जेक्ट्स अंतिम अनुरोध में उपयोग किए जाते हैं। अनुरोध से पहले आपके पास उनके पास पहुंच नहीं है। –

58

Btw, @ दाऊद Chelimsky का जवाब एक छोटे से फेरबदल की आवश्यकता हो सकती । क्या मैं (this StackOverflow post करने के लिए धन्यवाद) अपने एकीकरण/अनुरोध परीक्षण में कर रहा हूँ:

# file: spec/requests_helper.rb 
def login(user) 
    post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password 
end 
+2

जब मैं एक आरएसपीसी मॉडल स्पेक में 'लॉगिन उपयोगकर्ता 1' का उपयोग करता हूं, तो मुझे # jpwynn

+1

के लिए अपरिभाषित स्थानीय चर या विधि 'user_session_path' मिलता है। यह आपको मानता है 'devise_for: उपयोगकर्ता' 'config/path.rb' फ़ाइल में है। यदि आपने कुछ अलग निर्दिष्ट किया है, तो आपको तदनुसार अपना कोड बदलना होगा। –

+0

यह मेरे लिए काम करता है bu मुझे इसे थोड़ा संशोधित करना पड़ा। मैंने 'उपयोगकर्ता [ईमेल] '=> user.email' को' उपयोगकर्ता [उपयोगकर्ता नाम] '=> user.username' में बदल दिया है क्योंकि मेरा ऐप उपयोगकर्ता नाम के बजाय उपयोगकर्ता नाम का उपयोग करता है। – webdevguy

2

Fwiw, RSpec करने के लिए अपने टेस्ट :: ईकाई परीक्षण पोर्टिंग में, मैं कई के साथ प्रवेश करने (वसीयत) सत्र में सक्षम होना चाहता था मेरे अनुरोध चश्मा में। यह कुछ खुदाई ले लिया, लेकिन यह मेरे लिए काम करने के लिए मिला। रेल 3.2.13 और आरएसपीसी 2.13.0 का उपयोग करना।

# file: spec/support/devise.rb 
module RequestHelpers 
    def login(user) 
    ActionController::IntegrationTest.new(self).open_session do |sess| 
     u = users(user) 

     sess.post '/users/sign_in', { 
     user: { 
      email: u.email, 
      password: 'password' 
     } 
     } 

     sess.flash[:alert].should be_nil 
     sess.flash[:notice].should == 'Signed in successfully.' 
     sess.response.code.should == '302' 
    end 
    end 
end 

include RequestHelpers 

और ...

# spec/request/user_flows.rb 
require 'spec_helper' 

describe 'User flows' do 
    fixtures :users 

    it 'lets a user do stuff to another user' do 
    karl = login :karl 
    karl.get '/users' 
    karl.response.code.should eq '200' 

    karl.xhr :put, "https://stackoverflow.com/users/#{users(:bob).id}", id: users(:bob).id, 
     "#{users(:bob).id}-is-funny" => 'true' 

    karl.response.code.should eq '200' 
    User.find(users(:bob).id).should be_funny 

    bob = login :bob 
    expect { bob.get '/users' }.to_not raise_exception 

    bob.response.code.should eq '200' 
    end 
end 

संपादित: तय टाइपो

-1

आप बहुत आसानी से सत्र ठूंठ सकता है।

controller.session.stub(:[]).with(:user_id).and_return(<whatever user ID>) 

सभी रूबी विशेष ऑपरेटर वास्तव में विधियां हैं। 1+1 को कॉल करना 1.+(1) जैसा है, जिसका अर्थ है + केवल एक विधि है। इसी तरह, session[:user_id]session.[](:user_id)

+0

यह एक उचित समाधान की तरह लगता है। – superluminary

+1

यह एक अनुरोध spec में काम नहीं करता है, लेकिन केवल एक नियंत्रक spec में। – Machisuji

संबंधित मुद्दे