İstek özelliklerinde taslak kimlik doğrulaması


84

Bir istek belirtimi yazarken, oturumları ve / veya saplama denetleyici yöntemlerini nasıl ayarlarsınız? Entegrasyon testlerimde kimlik doğrulamasını durdurmaya çalışıyorum - rspec / istek

İşte bir test örneği

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

Yardımcı:

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

Ve kimlik doğrulamayı yöneten 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

Bu kaynaklara erişim neden mümkün değil?

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

Yanıtlar:


101

Bir istek ActionDispatch::IntegrationTestözelliği, denetleyici özellikleri gibi çalışmayan (saran ActionController::TestCase) ince bir sarmalayıcıdır . Kullanılabilir bir oturum yöntemi olmasına rağmen, desteklendiğini sanmıyorum (yani muhtemelen oradadır çünkü diğer araçlar için dahil edilen bir modül de bu yöntemi içerir).

Kullanıcıların kimliğini doğrulamak için kullandığınız eylemi göndererek oturum açmanızı öneririm. Tüm Kullanıcı fabrikaları için 'parola' (örneğin) parolası yaparsanız, bunun gibi bir şey yapabilirsiniz:

def login (kullanıcı)
  post login_path,: login => user.login,: password => 'password'
son

1
Teşekkürler David. Harika çalışıyor, ancak tüm bu istekleri yerine getirmek biraz abartılı gibi görünüyor?
Jonas Nielsen


6
Aynı zamanda bunu güvenilir bir şekilde yapmanın en basit yoludur. ActionDispatch::IntegrationTestgerçek tarayıcıları kullanmak zorunda kalmadan tarayıcılar aracılığıyla etkileşimde bulunan bir veya daha fazla kullanıcıyı simüle etmek için tasarlanmıştır. Tek bir örnekte potansiyel olarak birden fazla kullanıcı (yani oturum) ve birden fazla denetleyici vardır ve oturum / denetleyici nesneleri son istekte kullanılan nesnelerdir. Bir istekte bulunmadan önce bunlara erişiminiz yok.
David Chelimsky

17
page.driver.postCapybara ile kullanmak zorundayım
Ian Yang

@IanYang page.driver.post, Capybara'dan Jonas Nicklas'a göre ve API'leri test ediyor )
Epigene

61

Devise kullanıcıları için not ...

BTW, @David Chelimsky'nin cevabı, Devise kullanıyorsanız biraz ince ayar gerektirebilir . Entegrasyon / istek testimde ne yapıyorum ( bu StackOverflow gönderisi sayesinde ):

# file: spec/requests_helper.rb

# Rails 6
def login(user)
  post user_session_path, params: {
    user: {
      email: user.email, password: user.password
    }
  }
  follow_redirect!
end

# Rails 5 or older
def login(user)
  post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
end

2
daha sonra bir rspec model spesifikasyonunda 'login user1' kullandığımda, # <RSpec :: Core:
jpw

1
Bu devise_for :users, config/routes.rbdosyanızda olduğunu varsayar . Farklı bir şey belirlediyseniz, kodunuzu buna göre ayarlamanız gerekir.
fearless_fool

Bu benim için çalıştı ama biraz değiştirmem gerekti. Değiştim 'user[email]' => user.emailiçin 'user[username]' => user.usernamebenim app kullandığı bir oturum yerine e-posta olarak kullanıcı adı beri.
webdevguy

3

FWIW, Test :: Unit testlerimi RSpec'e aktarırken, istek özelliklerimde birden çok (tasarlama) oturumla oturum açabilmek istedim. Biraz kazmak gerekti, ama bunun benim için işe yaramasını sağladı. Rails 3.2.13 ve RSpec 2.13.0'ı Kullanma.

# 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

Ve...

# 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

Düzenleme : yazım hatası düzeltildi


-1

Oturumu da oldukça kolay bir şekilde başlatabilirsiniz.

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

Tüm Ruby özel operatörleri gerçekten yöntemlerdir. Arama 1+1ile aynı şey 1.+(1), yani +sadece bir yöntem. Benzer şekilde, session[:user_id]bir yöntem çağrı aynıdır []ilgili sessionolarak,session.[](:user_id)


Bu makul bir çözüm gibi görünüyor.
süper parlak ışık

2
Bu, bir istek spesifikasyonunda değil, yalnızca bir kontrolör spesifikasyonunda çalışır.
Machisuji

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.