रिक्वेस्ट स्पेस में स्टबलिंग ऑथेंटिकेशन


84

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

यहाँ एक परीक्षण का एक उदाहरण है

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)>'

जवाबों:


101

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

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

लॉगिन लॉगिन (उपयोगकर्ता)
  login_path,: login => user.login,: password => 'पासवर्ड' पोस्ट करें
समाप्त

1
धन्यवाद डेविड। यह बहुत अच्छा काम करता है, लेकिन ऐसा लगता है कि यह उन सभी अनुरोधों को पूरा करता है?
जोनास नीलसन

19
अगर मुझे लगा कि यह ओवरकिल है, तो मैंने इसकी सिफारिश नहीं की होगी :)
डेविड चेलिमस्की 12

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

17
मुझे page.driver.postCapybara
Ian Yang

@ इयानयांग page.driver.postएक एंटीपैटर्न हो सकता है, कैप्यबरा और परीक्षण एपीआई में जोनास निकलास के अनुसार )
एपिजेने

61

उपयोगकर्ताओं के लिए ध्यान दें ...

यदि आप डेविस का उपयोग कर रहे हैं तो BTW, @ डेविड चेलिमस्की के जवाब में थोड़ा ट्विकिंग की आवश्यकता हो सकती है । मैं अपने एकीकरण / अनुरोध परीक्षण में क्या कर रहा हूँ ( इस StackOverflow पोस्ट के लिए धन्यवाद ):

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

2
जब मैं rspec मॉडल कल्पना में 'login user1' का उपयोग करता हूं, तो मुझे # <RSpec :: Core:
jpw

1
इसका मतलब यह है आप devise_for :usersमें config/routes.rbफ़ाइल। यदि आपने कुछ अलग निर्दिष्ट किया है, तो आपको अपने कोड को उसी के अनुसार बदलना होगा।
निर्भय_फूल

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

3

FWIW, मेरे टेस्ट :: यूनिट टेस्ट को RSpec में पोर्ट करने में, मैं अपने अनुरोध चश्मे में कई (डेविस) सत्रों के साथ लॉगिन करने में सक्षम होना चाहता था। कुछ खुदाई हुई, लेकिन मेरे लिए यह काम कर गया। रेल का उपयोग 3.2.13 और RSpec 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, "/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, जैसा किsession.[](:user_id)


यह एक उचित समाधान की तरह लगता है।
१४:५४ पर सुपरल्युमरी

2
यह एक अनुरोध युक्ति में काम नहीं करता है, लेकिन केवल नियंत्रक युक्ति में होता है।
माकिसुजी

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.