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

这里是应用程序控制器文件(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

以及 home 控制器的 index 操作的默认测试(spec/controller/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: enticate”来运行它们,但是我想知道是否有办法使它们与该方法一起工作。

谢谢!

34522 次浏览

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

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

更新 (2013) : Matt Connolly 已经提供了一个 GIST,它同样适用于请求和控制器规格: < a href = “ http://GIST.github.com/4158961”rel = “ norefrer”> 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

信贷 给你

当使用 Rspec 测试 Grape API 时,以下语法可以工作

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

Valid_ session 在哪里

{'HTTP_AUTHORIZATION' => credentials}

还有

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

这些都是控制器和请求规格的伟大解决方案。

对于使用 Capybara 的特性测试,这里有一个使 HTTP 基本身份验证工作的解决方案:

Spec/support/when _ enticated. 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

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

我的解决办法是:

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

对于我来说,在 Rails 6中,我需要 rspec get 方法的关键字参数,比如. . get route, params: params, headers: headers

Auth Helper 方法

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 请求测试 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