Рельсы/тестирования RSpec сделать тесты с обычной проверкой подлинности http


здесь моя базовая аутентификация http в файле контроллера приложения (application_controller.РБ)

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.РБ)

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", чтобы запустить их, но я хотел бы знать, есть ли способ заставить их работать с этим методом.

спасибо!

5 62

5 ответов:

обновление (2013): Мэтт Коннолли предоставил суть, которая также работает для запроса и спецификаций контроллера:http://gist.github.com/4158961


другой способ сделать это, если у вас есть много тестов для запуска и не хотите включать его каждый раз (код сушилки):

создать /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

кредит здесь

Извините, что я не искал достаточно, решение, кажется, следующее:

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

при использовании Rspec для тестирования API Grape работает следующий синтаксис

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

где valid_session составляет

{'HTTP_AUTHORIZATION' => credentials}

и

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

некоторые ответы предлагают установить 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

эти большие решения для спецификаций регулятора и запроса.

для тестов функций с использованием Capybara, вот решение, чтобы сделать работу HTTP Basic authentication:

spec / support / when_authenticated.РБ

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