Rails/Rspec Накарайте тестовете да преминат с http основно удостоверяване

Ето моето http основно удостоверяване във файла на контролера на приложението (application_controller.rb)

before_filter :authenticate

protected

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

и тестът по подразбиране за индексното действие на моя домашен контролер (spec/controllers/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

Тестът не се изпълнява поради метода на удостоверяване. Бих могъл да коментирам "before_filter :authenticate", за да ги стартирам, но бих искал да знам дали има начин да ги накарам да работят с метода.

Благодаря ти!


person benoitr    schedule 22.09.2010    source източник


Отговори (6)


Актуализация (2013): Matt Connolly предостави GIST, който също работи за спецификации на заявка и контролер: http://gist.github.com/4158961


Друг начин да направите това, ако имате много тестове за изпълнение и не искате да ги включвате всеки път (код DRYer):

Създайте файл /spec/support/auth_helper.rb:

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

Във вашия тестов файл със спецификации:

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

Кредит тук

person iwasrobbed    schedule 08.03.2011
comment
показва, че заявката е нула за мен. някаква идея как да намеря заобиколно решение? - person chourobin; 06.04.2012
comment
За спецификации на заявка можете да имате няколко заявки, така че request е nil. Вместо това трябва да създадете env хеш env = {}, да го актуализирате във вашия метод http_login и след това да предадете env изрично, както в get '/', {}, env. - person Jonathan Tran; 24.10.2012
comment
Разширяване на горното, което работи за спецификации на заявка и контролер: gist.github.com/4158961 - person Matt Connolly; 28.11.2012
comment
+1 за същината от Мат Конъли; реши проблема ми, когато нищо друго не го направи. Между другото, опитах да използвам метода Rack::Test authorize - не работи. - person JESii; 02.03.2013
comment
Получавам Failure/Error: @request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(test_access1) NoMethodError: undefined method `env' for nil:NilClass, когато се опитам да използвам това.. защо? - person deepwinter; 19.06.2014
comment
Малко по-удобен подход към това: gist.github.com/lehresman/794f261708c82962763f - person Luke Ehresman; 29.07.2015
comment
Струва си да се спомене, че можете също да подадете информация за удостоверяване директно като трети аргумент: get '/repp/v1/contacts', { limit: 1, details: true }, { 'HTTP_AUTHORIZATION' => encoded_auth_key } - person Artur Beljajev; 01.12.2016

Съжалявам, че не потърсих достатъчно, решението изглежда е следното:

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
person benoitr    schedule 22.09.2010

Някои отговори предлагат да зададете request.env, което не е безопасно, защото заявката може да бъде nil и ще завършите с private method env' called for nil:NilClass, особено когато изпълнявате единични тестове с rspec -e

Правилният подход ще бъде:

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
person Daniel Garmoshka    schedule 22.12.2016
comment
Благодаря, това е единственият подход, който работи за моите системни тестове с помощта на Capybara. - person Simon Jakobi; 20.02.2019

Когато използвате Rspec за тестване на API на Grape, следният синтаксис работи

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

където е valid_session

{'HTTP_AUTHORIZATION' => credentials}

и

credentials = ActionController::HttpAuthentication::Token.encode_credentials("test_access1")
person deepwinter    schedule 19.06.2014

Това са страхотни решения за спецификации на контролера и заявката.

За тестове на функции, използващи Capybara, ето решение, за да накарате HTTP Basic удостоверяването да работи:

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

След това във вашата спецификация:

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

  # test examples
end
person madcow    schedule 09.09.2015
comment
Много полезно ! :) - person ; 16.05.2017
comment
Не работи в Chrome, IE и Safari (поне) https://medium.com/@lmakarov/say-goodbye-to-urls-with-embedded-credentials-b051f6c7b6a3 - person scoudert; 17.07.2019

Моето решение:

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

Използвайте gem webmock

можете да затегнете проверката чрез промяна:

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

URL - може да бъде регулярен израз

person Vitya Ivliiev    schedule 21.07.2020