Pisząc specyfikację żądania, w jaki sposób ustawiasz sesje i / lub metody kontrolera pośredniczącego? Próbuję zablokować uwierzytelnianie w moich testach integracji - rspec / requests
Oto przykład testu
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
Pomocnik:
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
Oraz ApplicationController, który obsługuje uwierzytelnianie:
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
Dlaczego nie można uzyskać dostępu do tych zasobów?
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)>'
źródło
ActionDispatch::IntegrationTest
jest przeznaczony do symulacji interakcji jednego lub większej liczby użytkowników za pośrednictwem przeglądarek bez konieczności korzystania z prawdziwych przeglądarek. W jednym przykładzie istnieje potencjalnie więcej niż jeden użytkownik (tj. Sesja) i więcej niż jeden kontroler, a obiekty sesji / kontrolera są tymi, które zostały użyte w ostatnim żądaniu. Nie masz do nich dostępu przed złożeniem wniosku.page.driver.post
z Kapibarąpage.driver.post
może być anty-wzorcem, według Jonasa Nicklasa z Kapibary i testujących API )Uwaga dla użytkowników Devise ...
BTW, odpowiedź @David Chelimsky może wymagać drobnych poprawek, jeśli używasz Devise . Co robię podczas testów integracji / żądań (dzięki temu postowi StackOverflow ):
# file: spec/requests_helper.rb def login(user) post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password end
źródło
devise_for :users
wconfig/routes.rb
aktach. Jeśli podałeś coś innego, będziesz musiał odpowiednio dostosować kod.'user[email]' => user.email
na,'user[username]' => user.username
ponieważ moja aplikacja używa nazwy użytkownika jako loginu zamiast adresu e-mail.FWIW, przenosząc moje Test :: Unit tests na RSpec, chciałem mieć możliwość logowania się z wieloma sesjami (devise) w specyfikacji mojego żądania. Wymagało to trochę kopania, ale udało mi się to. Korzystanie z Rails 3.2.13 i 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
I...
# 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
Edycja : poprawiona literówka
źródło
Możesz również dość łatwo zgasić sesję.
controller.session.stub(:[]).with(:user_id).and_return(<whatever user ID>)
Wszystkie operatory specjalne ruby są rzeczywiście metodami. Wywołanie
1+1
jest tym samym1.+(1)
, co, co oznacza, że+
jest to tylko metoda. Podobniesession[:user_id]
działa tak samo jak wywołanie metody[]
onsession
, assession.[](:user_id)
źródło
Znalazłem to bardzo pomocne dla Devise: https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)
źródło