74

这是我在应用程序控制器文件(application_controller.rb)中的http基本身份验证

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”来运行它们,但我想知道是否有办法让它们与该方法一起工作。

谢谢!

4

7 回答 7

141

更新(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

信用在这里

于 2011-03-08T22:21:35.803 回答
20

对不起,我没有寻求足够的,解决方案似乎如下:

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
于 2010-09-22T11:36:15.370 回答
8

一些答案建议设置request.env哪个是不安全的,因为 request 可以是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
于 2016-12-22T19:56:23.920 回答
4

使用 Rspec 测试 Grape API 时,以下语法有效

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

有效会话在哪里

{'HTTP_AUTHORIZATION' => credentials}

credentials = ActionController::HttpAuthentication::Token.encode_credentials("test_access1")
于 2014-06-19T06:14:04.287 回答
4

对我来说,使用 Rails 6,我需要 rspec get 方法的关键字参数,例如 ..get route, params: params, headers: headers

验证助手方法

module AuthHelper
  def headers(options = {})
    user = ENV['BASIC_AUTH_USER']
    pw = ENV['BASIC_AUTH_PASSWORD']

    { HTTP_AUTHORIZATION: ActionController::HttpAuthentication::Basic.encode_credentials(user,pw) }
  end
  def auth_get(route, params = {})
    get route, params: params, headers: headers
  end
end

rspec 请求测试。

describe HomeController, type: :request do    
  include AuthHelper

  describe "GET 'index'" do
    it "should be successful" do
      auth_get 'index'
      expect(response).to be_successful
    end
  end

end
于 2021-08-05T15:51:57.290 回答
3

这些是控制器和请求规范的绝佳解决方案。

对于使用 Capybara 的功能测试,这里有一个使 HTTP Basic 身份验证工作的解决方案:

规范/支持/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
于 2015-09-09T17:02:41.263 回答
0

我的解决方案:

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 - 可以是正则表达式

于 2020-07-21T08:58:47.543 回答