我对 Rails 还很陌生。 我们使用 Devise 来处理用户身份验证,并使用 RSpec 来测试应用程序 (Rails 4)。
我有一个
Admin
设计模型,可以访问一些经过身份验证的路线。以下是routes.rb
的摘录:
devise_for :admins
authenticate :admin do
get 'admin', to: 'admin#index'
end
它(显然)工作完美:如果我访问
/admin
,我会被重定向到/admins/sign_in
,并且一旦我登录(或者如果我已经在会话中),我就可以直接访问/admin
。
现在,据我了解,应该在内部测试路由
spec/routes/<controller_name>_routes_spec.rb
。我喜欢自行测试路线的想法(并且正确的控制器通过正确的操作处理每条路线等)。
当上述路线
authenticate
d时,我们面临测试路线的问题。包括
config.include Devise::TestHelpers[, type: :controller]
inside
spec/spec_helper.rb
仍然无法使 sign_in
(或 sign_[out|up]
)方法在路线规范中可用。
我们应该做什么?我们应该如何测试经过身份验证的路由? 我只是感觉不对,非身份验证的路由被测试为
spec/routes
,而身份验证的路由应该在集成测试中进行测试,使用水豚之类的东西手动填写登录表单。
(注:我读了this,但根本没有帮助)
您可以通过删除 spec_helper 配置中的条件来将设计助手包含在路由控制器中。我的看起来像这样:
...
RSpec.configure do |config|
config.include Devise::TestHelpers
...
end
def sign_in_user( user=nil )
@user = FactoryGirl.build(:user)
@user.skip_confirmation!
@user.save!
sign_in @user
end
或者,如果您想确保不会在奇怪的地方滥用设备,您可以将其包含在控制器和路由测试中。
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :routing
...
end
这一切都假设您正在输入规范文件。我的路由文件之一如下所示:
需要“spec_helper”
RSpec.describe WidgetsController, :type => :controller do
describe "routing" do
before(:each) do
sign_in_user
end
it "routes to #index" do
expect(:get => "/widgets").to route_to("widgets#index")
end
it "routes to #new" do
expect(:get => "/widgets/new").to route_to("widgets#new")
end
it "routes to #show" do
expect(:get => "/widgets/1").to route_to("widgets#show", :id => "1")
end
it "routes to #edit" do
expect(:get => "/widgets/1/edit").to route_to("widgets#edit", :id => "1")
end
it "routes to #create" do
expect(:post => "/widgets").to route_to("widgets#create")
end
it "routes to #update" do
expect(:put => "/widgets/1").to route_to("widgets#update", :id => "1")
end
it "routes to #destroy" do
expect(:delete => "/widgets/1").to route_to("widgets#destroy", :id => "1")
end
end
end
在你的rails_helper.rb中
RSpec.configure do |config|
config.include Devise::Test::IntegrationHelpers, type: :routing
end
在您的规格中:
describe 'admin routing' do
context 'when anonymous' do
it 'does not route to #index' do
expect(get: '/admin').not_to be_routable
end
end
context 'when authenticated' do
let(:user) { create(:user) }
before do
sign_in user
end
it 'routes to #index' do
expect(get: '/admin').to route_to('admin#index')
end
end
end