2010-09-22 12 views
58

Hier meine http Standardauthentifizierung in der Anwendungssteuerung Datei (application_controller.rb)Rails/Rspec Tests Pass mit http basic authentication

before_filter :authenticate 

protected 

def authenticate 
    authenticate_or_request_with_http_basic do |username, password| 
    username == "username" && password == "password" 
    end 
end 

und der Standard-Test für den Index Aktion meiner Heimsteuerung (spec/Controller/home_controller_spec.rb)

require 'spec_helper' 

describe HomeController do 

describe "GET 'index'" do 
    it "should be successful" do 
    get 'index' 
    response.should be_success 
    end 
end 

-Test nicht, da der Authentifizierungsverfahren auszuführen. Ich könnte "before_filter: authenticate" kommentieren, um sie auszuführen, aber ich würde gerne wissen, ob es einen Weg gibt, sie mit der Methode arbeiten zu lassen.

Vielen Dank!

Antwort

121

-Update: Matt Connolly hat einen GIST versehen, die für die Anfrage und Controller-Spezifikationen auch funktioniert: http://gist.github.com/4158961


Ein anderer Weg, dies zu tun, wenn Sie viele Tests haben zu laufen und nicht wollen, um es schließen jedes Mal (Dryer-Code):

eine /spec/support/auth_helper.rb Datei erstellen:

module AuthHelper 
    def http_login 
    user = 'username' 
    pw = 'password' 
    request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pw) 
    end 
end 

In Ihrem Test-Spez-Datei:

describe HomeController do 
    render_views 

    # login to http basic auth 
    include AuthHelper 
    before(:each) do 
    http_login 
    end 

    describe "GET 'index'" do 
    it "should be successful" do 
     get 'index' 
     response.should be_success 
    end 
    end 

end 

Kredit here

+0

gutes Beispiel, danke. –

+1

es zeigt anforderung ist für mich nil. Irgendeine Idee, wie man einen Workaround bekommt? – chourobin

+6

Für Anforderungsspezifikationen können Sie mehrere Anforderungen haben, also ist 'request'' nil'. Stattdessen müssen Sie einen env-Hash 'env = {}' erstellen, diesen in Ihrer http_login-Methode aktualisieren und dann das env explizit wie in 'get'/', {}, env' übergeben. –

17

Leider habe ich nicht genug suchen hat, scheint die Lösung, die folgenden zu sein:

describe "GET 'index'" do 
    it "should be successful" do 
    @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("username:password") 
    get 'index' 
    response.should be_success 
    end 
end 
4

Wenn Rspec mit Traube testen APIs, die folgende Syntax funktioniert

 post :create, {:entry => valid_attributes}, valid_session 

wo valid_session ist

{'HTTP_AUTHORIZATION' => credentials} 

und

credentials = ActionController::HttpAuthentication::Token.encode_credentials("test_access1") 
1

Dies sind große Lösungen für Steuerung und Anfrage Spezifikationen.

Für Feature-Tests Capybara verwenden, hier ist eine Lösung, die HTTP Basic-Authentifizierung funktioniert:

spec/support/when_authenticated.rb

RSpec.shared_context 'When authenticated' do 
    background do 
    authenticate 
    end 

    def authenticate 
    if page.driver.browser.respond_to?(:authorize) 
     # When headless 
     page.driver.browser.authorize(username, password) 
    else 
     # When javascript test 
     visit "http://#{username}:#{password}@#{host}:#{port}/"  
    end 
    end 

    def username 
    # Your value here. Replace with string or config location 
    Rails.application.secrets.http_auth_username 
    end 

    def password 
    # Your value here. Replace with string or config location 
    Rails.application.secrets.http_auth_password 
    end 

    def host 
    Capybara.current_session.server.host 
    end 

    def port 
    Capybara.current_session.server.port 
    end 
end 

Dann in der Spec:

feature 'User does something' do 
    include_context 'When authenticated' 

    # test examples 
end 
+0

Sehr hilfreich! :) –

4

Einige Antworten vorschlagen request.env zu setzen, die unsicher ist, weil Anfrage nil sein kann, und Sie werden mit private method env' called for nil:NilClass am Ende, vor allem, wenn einzelne Tests durchführen mit rspec -e

richtige Ansatz wird:

def http_login 
    user = 'user' 
    password = 'passw' 
    { 
    HTTP_AUTHORIZATION: ActionController::HttpAuthentication::Basic.encode_credentials(user,password) 
    } 
end 

get 'index', nil, http_login 

post 'index', {data: 'post-data'}, http_login 
Verwandte Themen