Rails / Rspec Lassen Sie Tests mit http-Basisauthentifizierung bestehen

69

Hier meine http Basisauthentifizierung in der Application Controller Datei (application_controller.rb)

before_filter :authenticate

protected

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

und der Standardtest für die Indexaktion meines Home-Controllers (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

Der Test wird aufgrund der Authentifizierungsmethode nicht ausgeführt. Ich könnte "before_filter: authenticate" kommentieren, um sie auszuführen, aber ich würde gerne wissen, ob es eine Möglichkeit gibt, sie mit der Methode arbeiten zu lassen.

Vielen Dank!

benoitr
quelle

Antworten:

138

Update (2013): Matt Connolly hat ein GIST bereitgestellt, das auch für Anforderungs- und Controller-Spezifikationen funktioniert: http://gist.github.com/4158961


Eine andere Möglichkeit, dies zu tun, wenn Sie viele Tests ausführen müssen und diese nicht jedes Mal einschließen möchten (DRYer-Code):

Erstellen Sie eine /spec/support/auth_helper.rb-Datei:

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

In Ihrer Testspezifikationsdatei:

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

Gutschrift hier

Ich wurde ausgeraubt
quelle
1
es zeigt, dass die Anfrage für mich gleich Null ist. Irgendeine Idee, wie man eine Problemumgehung bekommt?
Chourobin
6
Für Anfrage Spezifikationen, können Sie mehrere Anfragen haben kann, so requestist nil. Stattdessen müssen Sie einen env-Hash erstellen env = {}, diesen in Ihrer http_login-Methode aktualisieren und dann den env explizit wie in übergeben get '/', {}, env.
Jonathan Tran
6
Erweitern Sie das Obige, das für Anforderungs- und Controller-Spezifikationen funktioniert
Matt Connolly
+1 für das Wesentliche von Matt Connolly; es löste mein Problem, als nichts anderes tat. Übrigens habe ich versucht, die Rack :: Test-Autorisierungsmethode zu verwenden - hat nicht funktioniert.
JESii
Ich erhalte Fehler / Fehler: @ request.env ['HTTP_AUTHORIZATION'] = ActionController :: HttpAuthentication :: Token.encode_credentials ("test_access1") NoMethodError: undefinierte Methode `env 'für nil: NilClass, wenn ich versuche, dies zu verwenden .. warum ?
Deepwinter
18

Entschuldigung, ich habe nicht genug gesucht, die Lösung scheint folgende 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
benoitr
quelle
7

Einige Antworten schlagen vor, festzulegen, request.envwas unsicher ist, da eine Anfrage möglich ist nilund Sie am Ende davon betroffen sind private method env' called for nil:NilClass, insbesondere wenn Sie einzelne Tests mit ausführenrspec -e

Der richtige Ansatz wird sein:

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
Daniel Garmoshka
quelle
Vielen Dank, dies ist der einzige Ansatz, der für meine Systemtests mit Capybara funktioniert hat.
Simon Jakobi
4

Wenn Sie Rspec zum Testen von Trauben-APIs verwenden, funktioniert die folgende Syntax

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

wo valid_session ist

{'HTTP_AUTHORIZATION' => credentials}

und

credentials = ActionController::HttpAuthentication::Token.encode_credentials("test_access1")
Tiefwinter
quelle
3

Dies sind großartige Lösungen für Controller- und Anforderungsspezifikationen.

Für Funktionstests mit Capybara finden Sie hier eine Lösung, mit der 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 Ihrer Spezifikation:

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

  # test examples
end
verrückte Kuh
quelle
Sehr hilfreich ! :)
Funktioniert nicht, in Chrome, IE und Safari (zumindest) können Sie sich nicht mehr mit einer URL bei http auth anmelden
scoudert
0

Meine Lösung:

stub_request(method, url).with(
  headers: { 'Authorization' => /Basic */ }
).to_return(
  status: status, body: 'stubbed response', headers: {}
)

Verwenden Sie Edelstein Webmock

Sie können die Überprüfung durch Änderung verschärfen:

/Basic */ -> "Basic #{Base64.strict_encode64([user,pass].join(':')).chomp}"

URL - kann ein regulärer Ausdruck sein

Vitya Ivliiev
quelle