ruby-on-rails Rails/Rspec使用http基本身份验证使测试通过

yeotifhr  于 2023-01-22  发布在  Ruby
关注(0)|答案(7)|浏览(159)

下面是应用程序控制器文件(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"来运行它们,但我想知道是否有办法使它们与该方法一起工作。
谢谢大家!

sxissh06

sxissh061#

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

信用额度here-Archived site

mrphzbgm

mrphzbgm2#

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

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
oyxsuwqo

oyxsuwqo3#

一些答案建议设置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
ljo96ir5

ljo96ir54#

对于我来说,使用Rails6时,我需要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
new9mtju

new9mtju5#

使用Rspec测试GrapeAPI时,可以使用以下语法

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

其中,有效会话为

{'HTTP_AUTHORIZATION' => credentials}

以及

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

7z5jn7bk6#

这些都是控制器和请求规格的很好的解决方案。
对于使用Capybara的特性测试,下面是一个使HTTP Basic身份验证工作的解决方案:

规范/支持/验证时.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
ep6jt1vc

ep6jt1vc7#

我的解决方案:

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

使用gem网络模拟
您可以通过更改来加强验证:

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

URL-可以是正则表达式

相关问题