web-dev-qa-db-fra.com

Authentification de remplacement dans la spécification de demande

Lors de l'écriture d'une spécification de demande, comment définissez-vous les sessions et/ou les méthodes de contrôleur de stub? J'essaie de bloquer l'authentification dans mes tests d'intégration - rspec/requests

Voici un exemple de test

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

L'aide:

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

Et l'ApplicationController qui gère l'authentification:

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

Pourquoi n'est-il pas possible d'accéder à ces ressources?

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)>'
83
Jonas Nielsen

Une spécification de demande est une enveloppe mince autour de ActionDispatch::IntegrationTest , qui ne fonctionne pas comme les spécifications du contrôleur (qui encapsulent ActionController::TestCase ). Même s'il existe une méthode de session, je ne pense pas qu'elle soit prise en charge (c'est-à-dire qu'elle est probablement là car un module qui est inclus pour d'autres utilitaires inclut également cette méthode).

Je vous recommande de vous connecter en publiant les actions que vous utilisez pour authentifier les utilisateurs. Si vous créez le mot de passe "mot de passe" (par exemple) pour toutes les usines d'utilisateurs, vous pouvez faire quelque chose comme ceci:

 def login (utilisateur) 
 post login_path,: login => user.login,: mot de passe => 'mot de passe' 
 fin 
100
David Chelimsky

Remarque pour les utilisateurs de Devise ...

BTW, la réponse de @David Chelimsky peut nécessiter un petit ajustement si vous utilisez Devise . Ce que je fais dans mes tests d'intégration/de requêtes (grâce à ce post StackOverflow ):

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

FWIW, en portant mes tests Test :: Unit sur RSpec, je voulais pouvoir me connecter avec plusieurs sessions (devise) dans mes spécifications de demande. Il a fallu creuser, mais cela a fonctionné pour moi. Utilisation de Rails 3.2.13 et 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

Et...

# 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

Modifier : faute de frappe fixe

3
turboladen