如何使用RSpec和Devise / CanCan进行集成testing?
如果我有一个Devise模型用户,其中只有那些angular色:admin的用户才能查看某个url,那么如何编写RSpec集成testing来检查该url的状态是否返回200?
def login(user) post user_session_path, :email => user.email, :password => 'password' end
这个问题在这个问题的答案中是伪build议的: 在请求规范中对authentication进行了stubbing ,但是我不能让它和devise一起工作。 CanCan在检查Ability时没有收到一个无用户,这个用户自然没有正确的权限。
在集成规范中没有对控制器的访问权限,所以我不能存根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
注意!!! :自问题提出以来所有这一切都改变了。 目前最好的方法是: http : //github.com/plataformatec/devise/wiki/How-To : -Test-with-Capybara
@ pschuegr自己的答案让我越过了界限。 为了完整性,这是我所做的,可以让我轻松设置请求规格和控制器规格(使用FactoryGirl创build用户实例):
在/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
然后在请求规格:
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
类似地,在控制器规范中使用“signed_in_as_valid_user”(将FactoryDesigner的用户包装在Devise :: TestHelpers的sign_in方法中)
啊,那么近。 这是诀窍 – 我错过了正确的参数forms,并redirect。
post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
我用了一个稍微不同的方法,使用Warden :: Test :: Helpers。
在我的规格/支持/ 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
然后把它包含在RSpec的spec_helper.rb中:
RSpec.configure do |config| config.include RequestMacros, :type => :request end
然后在请求规格本身:
describe "index" do it "redirects to home page" do sign_in_as_a_user visit "/url" page.should_not have_content 'content' end end
与post_via_redirect user_session_path
方法相反,这实际上起作用,例如,允许我在before_filters中使用current_user。
你可以创build一个macros(/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
你也可以包含你想要的任何CanCan属性。 那么,在你的规范中:
describe YourController do login_user it "should ..." do end
我发现这个链接非常有帮助https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec);
截至2017年年中,我认为我们还有更好的机会将devise融入我们的Rspecs。 我们能够利用辅助方法sign in
来validation存根validation,定义如下:
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
您还应该在spec_helper.rb
或rails_helper.rb
引用中追加新创build的文件:
require 'support/controller_helpers' ... RSpec.configure do |config| ... config.include Devise::TestHelpers, :type => :controller config.include ControllerHelpers, :type => :controller ... end
然后在方法只是放置在方法身体sign_in
的开始为authentication用户的上下文,你都设置。 最新的细节可以在devise文档中find