然而,我仍然想知道如何满足未来的需求,我可以对需要登录用户的控制器进行集成测试......对于过去的其他非设计应用程序,这很简单如下所示:describe SomeController dolet(:user) { FactoryGirl.create(:user) }{ valid_sign_in 用户} 之前...我的帮手就在这里 def valid_sign_in(user)访问 signin_path填写电子邮件",使用:user.email填写密码",用:user.password取消选中(:remember_me)click_button "登录"# 不使用 Capybara 时也登录.cookies[:remember_token] = user.remember_token结尾 解决方案 有两个问题在起作用:1.rspec/控制器与 rspec/请求我试图在规范/控制器下进行集成测试.根据 https://github.com/jnicklas/capybara#readme,你需要把规范/请求或规范/集成中的 Capybara 规范.根据 https://stackoverflow.com/a/5803121/9344:请求规范是一个薄的包装器ActionDispatch::IntegrationTest,它不像控制器那样工作规格(包装 ActionController::TestCase).即使有一个会话方法可用,我认为它不受支持(即它是可能是因为一个模块包含在其他实用程序中也包括那个方法).最初这可以通过 Devise 通过辅助方法解决,例如:# 文件:spec/requests_helper.rb定义登录(用户)post_via_redirect user_session_path, 'user[email]' =>user.email, '用户 [密码]' =>用户密码结尾但是我已经实施的官方/最新解决方案(但请参阅下面的第二点,了解为什么它没有解决我的问题),可以在 https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara2.Devise::HelperTests 用于控制器/视图测试,而不是集成测试.如果我想在控制器上做一些测试,我可以使用 Devise::TestHelpers(通过 spec_helper.rb 引用),但即使这样我也没有获得 Capybara 集成测试的功能Devise::TestHelpers 是专门为控制器/视图测试而不是集成测试编写的.参见 rspec &设计测试助手.总而言之,我想在控制器测试中做的事情无法完成,因为它实际上是一个集成测试,并且会话等不适用于规范/控制器.但是,有一些 Devise 测试助手可用于帮助进行控制器/视图测试.更新我在很久以后重新审视了这一点,现在已经让 Warden 助手在我的集成测试中发挥作用.欢呼!在我的 448 次测试中,这已经缩短了 8-10 秒.诀窍是 https://github 上的一个新条目.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara.具体:Capybara-Webkit 如果您在使用 Warden 的 login_as 方法时遇到问题使用 capybara-webkit 驱动程序,尝试将 run_callbacks 设置为 falselogin_as 选项结构user = Factory.create(:user)login_as(user, :scope =>:user,:run_callbacks =>错误的)总而言之,每次我需要一个经过身份验证的用户进行集成测试时,不必每次都进行实际的表单填写和发布,现在我只需要 login_as(user, :scope => :user, :run_callbacks => false)(当然重构为辅助方法).Update: see end of post for how the specs now work now that I have my specs in spec/requests instead of spec/controllers. Still wondering how to get a valid signed in user for integration tests with my controllers.I'm working with Devise and CanCan for the first time and am having difficulty doing the most basic of integration tests whereby I'm verifying that a logged in user is...well...logged in. I have read countless posts and answers dealing with Devise and RSpec integration tests (i.e. speeding them up by accessing the session directly via https://github.com/plataformatec/devise/wiki/How-To%3a-Test-with-Capybara, http://schneems.com/post/15948562424/speed-up-capybara-tests-with-devise, and Capybara, RSpec and Devise: any way to make integration tests faster by circumventing slow login and setting session directly?, but I have been unable to even get a standard post working as expected and I'm baffled:Development environment works fine (can log in and get redirected to proper page, with navigation login link changed to logout, etc.).test.log indicates no problems until it does a 302 redirect to http://www.example.com instead of my root_path.By the plethora of users with similar issues with varying solutions, I'm obviously not the only one who has had this problem as various aspects of the session etc. are unavailable in different scenarios.Stripped down test:subject { page }describe 'should be able to log in' do before do visit '/users/sign_in' user = FactoryGirl.create(:admin) #user.add_role :admin fill_in 'Username', with: user.username fill_in 'Password', with: user.password click_on 'Sign in' end it { should have_link 'Logout' }end...Relevant log.test output: Started POST "/users/sign_in" for 127.0.0.1 at 2012-11-06 17:31:10 -0800 Processing by Devise::SessionsController#create as HTML Parameters: {"utf8"=>"✓", "user"=>{"username"=>"username1", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"} [1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."username" = 'username1' LIMIT 1[0m [1m[35m (0.0ms)[0m SAVEPOINT active_record_1 [1m[36m (0.0ms)[0m [1mRELEASE SAVEPOINT active_record_1[0m [1m[35m (0.0ms)[0m SAVEPOINT active_record_1 [1m[36m (0.1ms)[0m [1mUPDATE "users" SET "last_sign_in_at" = '2012-11-07 01:31:10.722712', "current_sign_in_at" = '2012-11-07 01:31:10.722712', "last_sign_in_ip" = '127.0.0.1', "current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at" = '2012-11- 07 01:31:10.723051' WHERE "users"."id" = 1[0m [1m[35m (0.0ms)[0m RELEASE SAVEPOINT active_record_1 Redirected to http://www.example.com/ Completed 302 Found in 12ms (ActiveRecord: 0.0ms)Stripped down routes.rb:authenticated :user do root :to => 'home#index'endroot :to => "home#index"devise_for :usersresources :usersStripped down Ability:class Ability include CanCan::Ability def initialize(user) user ||= User.new # guest user (not logged in) if user.has_role? :admin can :manage, :all end ...And to be thorough, the current Gemfile:source 'https://rubygems.org'gem 'rails', '3.2.8'gem "bootstrap-sass", "~> 2.1.0.1"gem 'faker', '1.1.2'gem 'will_paginate', '~> 3.0.3'gem 'bootstrap-will_paginate', '~> 0.0.9'gem 'jquery-rails'gem 'client_side_validations'gem 'thin'gem "devise", "~> 2.1.2"gem "cancan", "~> 1.6.8"gem "rolify", "~> 3.2.0"gem "simple_form", "~> 2.0.4"group :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3'endgroup :development, :test do gem 'sqlite3', '1.3.5' gem "rspec-rails", "~> 2.11.4" gem 'guard-rspec', '1.2.1' #gem 'listen', github: 'guard/listen', branch: 'polling/double' gem 'guard-spork' gem 'guard-cucumber' gem 'spork', '0.9.2' gem "factory_girl_rails", ">= 4.1.0"endgroup :development do gem 'annotate', '2.5.0' gem "quiet_assets", ">= 1.0.1"end group :test do gem 'capybara', ">= 1.1.2" gem "email_spec", ">= 1.2.1" gem "cucumber-rails", ">= 1.3.0", :require => false gem "database_cleaner", ">= 0.9.1" gem "launchy", ">= 2.1.2" gem 'rb-fsevent', '0.9.1', :require => false gem 'growl', '1.0.3' gem 'terminal-notifier-guard'endgroup :production do gem 'pg', '0.12.2' endThere's another user who had issues with this basic task, but it turned out it was simply a syntax error (see Login integration test with rspec/devise) so I'm sure I'm just missing something very obvious.Update:You have got to be kidding me. After leaving it for a couple hours, it turns out I had this spec for some reason in spec/controllers, when simply switching it over to spec/requests made everything green.I quote:Found at https://github.com/jnicklas/capybara#readmeHowever, I'm still wondering how for future requirements I can do integration tests on my controllers that will need to have a logged in user.... for other non-Devise apps in the past, this has been as simple as something like the following:describe SomeController do let(:user) { FactoryGirl.create(:user) } before { valid_sign_in user }...where my helper is simply def valid_sign_in(user) visit signin_path fill_in "Email", with: user.email fill_in "Password", with: user.password uncheck(:remember_me) click_button "Sign In" # Sign in when not using Capybara as well. cookies[:remember_token] = user.remember_token end 解决方案 There are two issues at play:1. rspec/controller vs rspec/requestsI was attempting to do an integration test under spec/controller. As per https://github.com/jnicklas/capybara#readme, you need to put Capybara specs in spec/requests or spec/integration. As per https://stackoverflow.com/a/5803121/9344:Originally this could be solved with Devise via a helper method something like:# file: spec/requests_helper.rbdef login(user) post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.passwordendBut the official/latest solution, which I had implemented already (but see point two below for why it didn't solve my issue), can be found at https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara2. Devise::HelperTests are for controller/view tests, not integration tests.If I want to do some tests on a controller, I can use the Devise::TestHelpers (referenced via spec_helper.rb) but even then I don't get functionality for Capybara integration tests as the Devise::TestHelpers are specifically written for controller/view tests, not integration tests. See rspec & devise test helpers.In summary, what I wanted to do in a controller test can't be done because it was really an integration test and the session etc. isn't available for use in spec/controllers. However, there are some Devise test helpers that can be used to help do controller/view tests.UPDATEI revisited this much later, and have now got the Warden helpers functioning on my integration tests. Hurrah! This has taken off 8-10 seconds on my 448 tests. The trick was a new entry on https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara. Specifically:user = Factory.create(:user)login_as(user, :scope => :user,:run_callbacks => false)In summary, instead of having to do an actual form fill and post for each time I needed an authenticated user for an integration test, now I just need login_as(user, :scope => :user, :run_callbacks => false) (of course refactored out into a helper method). 这篇关于Capybara、Devise、CanCan 和 RSpec 集成测试:有效登录 302 重定向到 example.com的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-30 23:32