这是我在应用程序控制器文件(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”来运行它们,但我想知道是否有办法让它们与该方法一起工作。
谢谢!
更新(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
对不起,我没有寻求足够的,解决方案似乎如下:
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
一些答案建议设置不安全的 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
对我来说,使用 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
使用 Rspec 测试 Grape API 时,以下语法有效
post :create, {:entry => valid_attributes}, valid_session
有效会话在哪里
{'HTTP_AUTHORIZATION' => credentials}
和
credentials = ActionController::HttpAuthentication::Token.encode_credentials("test_access1")
这些是控制器和请求规范的绝佳解决方案。
对于使用 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
我的解决方案:
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 - 可以是正则表达式
不定期副业成功案例分享
request
是nil
。相反,您需要创建一个 env 哈希env = {}
,在您的 http_login 方法中更新它,然后像get '/', {}, env
中那样显式传递 env。