Ruby-on-rails 如何使用 RSpec 和 Devise/CanCan 进行集成测试?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5865555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to do integration testing with RSpec and Devise/CanCan?
提问by pschuegr
If I have a Devise model User, of which only those users with role :admin are allowed to view a certain url, how can I write an RSpec integration test to check that the status returns 200 for that url?
如果我有一个 Devise 模型用户,其中只有那些具有角色 :admin 的用户才能查看某个 url,我如何编写 RSpec 集成测试来检查该 url 的状态是否返回 200?
def login(user)
post user_session_path, :email => user.email, :password => 'password'
end
This was pseudo-suggested in the answer to this question: Stubbing authentication in request spec, but I can't for the life of me get it to work with devise. CanCan is receiving a nil User when checking Ability, which doesn't have the correct permissions, naturally.
这在这个问题的答案中是伪建议的:Stubbing authentication in request spec,但我一生都无法让它与设计一起工作。CanCan 在检查能力时收到一个 nil 用户,这自然没有正确的权限。
There's no access to the controller in integration specs, so I can't stub current_user, but I'd like to do something like this.
在集成规范中无法访问控制器,所以我不能存根 current_user,但我想做这样的事情。
describe "GET /users" do
it "should be able to get" do
clear_users_and_add_admin #does what it says...
login(admin)
get users_path
response.status.should be(200)
end
end
NOTE!!!: all this has changed since the question was asked. The current best way to do this is here: http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara
笔记!!!: 自从提出这个问题以来,这一切都发生了变化。目前最好的方法是在这里:http: //github.com/plataformatec/devise/wiki/How-To: -Test-with-Capybara
回答by Matt Connolly
@pschuegr's own answer got me across the line. For completeness, this is what I did that gets me easily set up for both request specs and controller specs (using FactoryGirl for creating the user instance):
@pschuegr 自己的回答让我跨界了。为了完整起见,这就是我所做的,它让我可以轻松地为请求规范和控制器规范进行设置(使用 FactoryGirl 创建用户实例):
in /spec/support/sign_in_support.rb:
在 /spec/support/sign_in_support.rb 中:
#module for helping controller specs
module ValidUserHelper
def signed_in_as_a_valid_user
@user ||= FactoryGirl.create :user
sign_in @user # method from devise:TestHelpers
end
end
# module for helping request specs
module ValidUserRequestHelper
# for use in request specs
def sign_in_as_a_valid_user
@user ||= FactoryGirl.create :user
post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password
end
end
RSpec.configure do |config|
config.include ValidUserHelper, :type => :controller
config.include ValidUserRequestHelper, :type => :request
end
Then in request spec:
然后在请求规范中:
describe "GET /things" do
it "test access to things, works with a signed in user" do
sign_in_as_a_valid_user
get things_path
response.status.should be(200)
end
end
describe "GET /things" do
it "test access to things, does not work without a signed in user" do
get things_path
response.status.should be(302) # redirect to sign in page
end
end
and similarly, use 'signed_in_as_valid_user' in controller specs (which wraps Devise::TestHelpers sign_in method with a user from FactoryGirl)
同样,在控制器规范中使用“signed_in_as_valid_user”(它使用 FactoryGirl 的用户包装 Devise::TestHelpers sign_in 方法)
回答by pschuegr
Ah, so close. This does the trick - I was missing the proper parameter form, and the redirecting.
啊,这么近。这可以解决问题 - 我缺少正确的参数形式和重定向。
post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
回答by Jure Triglav
I used a slightly different approach, using the Warden::Test::Helpers.
我使用了稍微不同的方法,使用 Warden::Test::Helpers。
In my spec/support/macros.rb I added:
在我的 spec/support/macros.rb 中,我添加了:
module RequestMacros
include Warden::Test::Helpers
# for use in request specs
def sign_in_as_a_user
@user ||= FactoryGirl.create :confirmed_user
login_as @user
end
end
And then included that in RSpec's config in spec_helper.rb:
然后将其包含在 spec_helper.rb 中的 RSpec 配置中:
RSpec.configure do |config|
config.include RequestMacros, :type => :request
end
And then in the request specs themselves:
然后在请求规范中:
describe "index" do
it "redirects to home page" do
sign_in_as_a_user
visit "/url"
page.should_not have_content 'content'
end
end
In contrast to the post_via_redirect user_session_pathmethod, this actually works and allows me to use current_user in before_filters, for example.
与该post_via_redirect user_session_path方法相反,这实际上有效并允许我在 before_filters 中使用 current_user,例如。
回答by Shimaa Marzouk
回答by w1t3k
As of mid 2017, we have one more, in my opinion better opprotunity to integrate devise in our Rspecs. We are able to utilize stub authentization with helper method sign indefined as described below:
到 2017 年年中,我们还有一个,在我看来更好的机会将设计集成到我们的 Rspecs 中。我们能够使用存根身份验证和辅助方法sign in定义如下:
module ControllerHelpers
def sign_in(user = double('user'))
if user.nil?
allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user})
allow(controller).to receive(:current_user).and_return(nil)
else
allow(request.env['warden']).to receive(:authenticate!).and_return(user)
allow(controller).to receive(:current_user).and_return(user)
end
end
end
You should also append in spec_helper.rbor rails_helper.rbreference to newly created file:
您还应该附加spec_helper.rb或rails_helper.rb引用新创建的文件:
require 'support/controller_helpers'
...
RSpec.configure do |config|
...
config.include Devise::TestHelpers, :type => :controller
config.include ControllerHelpers, :type => :controller
...
end
Then in method just place at the beginning of the method body sign_infor context for authenticated user and you are all set. Up to date details can be found in devise docs here
然后在方法中,只需将方法体的开头放在经过sign_in身份验证的用户的上下文中,就可以了。可以在此处的设计文档中找到最新的详细信息
回答by Spyros
You can create a macro (/spec/support/controller_macros.rb) and write something like :
您可以创建一个宏 (/spec/support/controller_macros.rb) 并编写如下内容:
module ControllerMacros
def login_user
before(:each) do
@request.env["devise.mapping"] = :user
@user = Factory(:user)
sign_in @user
end
end
end
You can also include any CanCan attributes you want. Then, in your spec :
您还可以包含所需的任何 CanCan 属性。然后,在您的规范中:
describe YourController do
login_user
it "should ..." do
end

