Rails / Rspec使测试通过http基本认证通过


69

这是我在应用程序控制器文件(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”来运行它们,但是我想知道是否有办法使它们与该方法一起使用。

谢谢!

Answers:


138

更新(2013):Matt Connolly提供了GIST,该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

信用在这里


1
它表明请求对我来说是零。任何想法如何获得解决方法?
chourobin

6
对于请求规范,您可以有多个请求,所以request也是nil。相反,您需要创建一个env哈希env = {},在您的http_login方法中对其进行更新,然后像中一样显式传递env get '/', {}, env
乔纳森·崔

6
扩展上述内容,以适用于请求和控制器规范:gist.github.com/4158961
Matt Connolly

马特·康诺利(Matt Connolly)的主意+1;它什么也没解决就解决了我的问题。顺便说一句,我试图使用Rack :: Test授权方法-无效。
JESii 2013年

我收到失败/错误:@ request.env ['HTTP_AUTHORIZATION'] = ActionController :: HttpAuthentication :: Token.encode_credentials(“ test_access1”)NoMethodError:当我尝试使用此方法时,nil:NilClass的未定义方法`env'..为什么?
deepwinter 2014年

18

抱歉,我没有找到足够的解决方案,似乎是这样的:

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

7

一些答案建议设置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进行系统测试的唯一方法。
西蒙·雅各比

4

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

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

在哪里valid_session

{'HTTP_AUTHORIZATION' => credentials}

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

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

很有帮助 !:)

不起作用,在Chrome,IE和Safari中(至少),您不能再使用URL登录http auth
scoudert

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.