创建的对象在rspec中的控制器操作中不可用?

时间:2013-12-29 20:41:27

标签: ruby-on-rails ruby rspec ruby-on-rails-3.2 capybara

我正在尝试在帮助程序模块中创建一个登录操作,该操作将创建一个新用户并以该用户身份登录。由于我使用capybara与capybara-webkit驱动程序,post或submit方法不可用,所以我不能简单地使用适当的参数发布到登录路径。我当前的方法是实际访问登录路径并使用新创建的用户的用户名和密码填写登录表单。这是我正在尝试创建的辅助函数(在spec / support / session_macros.rb中):

module SessionMacros
  def log_in
    user = User.create(first_name: 'Test',
               last_name: 'Test',
               email: 'foo@example.com',
               password: 'secret',
               password_confirmation: 'secret'
           )
    visit admin_login_path
    fill_in 'email', with: user.email
    fill_in 'password', with: 'secret'
    click_button 'Log in'
  end
end

在spec / spec_helper.rb中:

config.include SessionMacros

在config / routes.rb中:

  namespace :admin do
    resources :sessions
    get 'login', to: 'sessions#new', as: 'login'
    get 'logout', to: 'sessions#destroy', as: 'logout'
  end

在app / views / admin / sessions / new.html.haml

.login-form
  %h3 Sign in
  = form_tag admin_sessions_path do
    = content_tag :div, flash[:alert], class: 'alert' if flash[:alert]
    = text_field_tag :email, params[:email], placeholder: 'Email'
    = password_field_tag :password, params[:password], placeholder: 'Password'
    = submit_tag "Log in", class: 'button'

在app / controllers / admin / sessions_controller.rb

def create
  user = User.find_by_email(params[:email])
  if user && user.authenticate(params[:password])
    session[:user_id] = user.id
    redirect_to admin_root_url
  else
    flash[:alert] = 'Invalid email or password'
    redirect_to admin_login_path
  end
end

我正在使用功能规范中的帮助程序(spec / features / admin / events_spec.rb):

before :each do
  log_in
  visit admin_events_path
end

问题在于我运行的测试:js => true将导致sessions_controller #create函数无法查看在log_in方法开头创建的用户。这是我做过的一些控制台测试的结果:

[5, 14] in /Users/Me/projects/cms/spec/support/session_macros.rb
   5                 email: 'foo@example.com',
   6                 password: 'secret',
   7                 password_confirmation: 'secret'
   8             )
   9      debugger
=> 10      visit admin_login_path
   11      fill_in 'email', with: user.email
   12      fill_in 'password', with: 'secret'
   13      click_button 'Log in'
   14    end
(rdb:1) User.all
[#<User id: 1, email: "foo@example.com", password_digest: "$2a$10$Pxv3GlNnEPx0PnFOmP/MUeP0SMs4vD925vjhoaViKA8o...", created_at: "2013-12-29 20:34:47", updated_at: "2013-12-29 20:34:47", first_name: "Test", last_name: "Test">]
(rdb:1) continue
/Users/Me/projects/cms/app/controllers/admin/sessions_controller.rb:7
if user && user.authenticate(params[:password])

[2, 11] in /Users/Me/projects/cms/app/controllers/admin/sessions_controller.rb
   2    skip_before_filter :authorize, :authenticate
   3
   4    def create
   5      user = User.find_by_email(params[:email])
   6      debugger
=> 7      if user && user.authenticate(params[:password])
   8        session[:user_id] = user.id
   9        redirect_to admin_root_url
   10      else
   11        flash[:alert] = 'Invalid email or password'
(rdb:6) User.all
[]
(rdb:6)

请注意,当我不使用时:js =&gt;是的,它工作正常:

[5, 14] in /Users/Me/projects/cms/spec/support/session_macros.rb
   5                 email: 'foo@example.com',
   6                 password: 'secret',
   7                 password_confirmation: 'secret'
   8             )
   9      debugger
=> 10      visit admin_login_path
   11      fill_in 'email', with: user.email
   12      fill_in 'password', with: 'secret'
   13      click_button 'Log in'
   14    end
(rdb:1) User.all
[#<User id: 1, email: "foo@example.com", password_digest: "$2a$10$ryLIQcV7foWQdWLSObzUnuGsbAPzKvPVe2PRzGuTEGRM...", created_at: "2013-12-29 20:37:47", updated_at: "2013-12-29 20:37:47", first_name: "Test", last_name: "Test">]
(rdb:1) continue
/Users/Me/projects/cms/app/controllers/admin/sessions_controller.rb:7
if user && user.authenticate(params[:password])

[2, 11] in /Users/Me/projects/cms/app/controllers/admin/sessions_controller.rb
   2    skip_before_filter :authorize, :authenticate
   3
   4    def create
   5      user = User.find_by_email(params[:email])
   6      debugger
=> 7      if user && user.authenticate(params[:password])
   8        session[:user_id] = user.id
   9        redirect_to admin_root_url
   10      else
   11        flash[:alert] = 'Invalid email or password'
(rdb:1) User.all
[#<User id: 1, email: "foo@example.com", password_digest: "$2a$10$ryLIQcV7foWQdWLSObzUnuGsbAPzKvPVe2PRzGuTEGRM...", created_at: "2013-12-29 20:37:47", updated_at: "2013-12-29 20:37:47", first_name: "Test", last_name: "Test">]

当我使用Selenium和webkit驱动程序进行javascript时,会发生这种情况。什么给这里?我担心在与Capybara进行JS集成测试时,我可能会从根本上误解数据库交互。我也担心这可能是一个XY问题,因为我甚至不确定我的log_in方法方法。如果有人能够更好地实现我可以与Javascript兼容的log_in助手,或者为什么我的数据库对象无法在Javascript模式的控制器中找到,我真的很感激。

1 个答案:

答案 0 :(得分:0)

似乎RSpec为每个测试使用数据库事务,并且此事务中的任何更改对于应用程序代码都是不可见的。播放Rspec的use_transactional_fixtures选项(1),Capybara docs (2)和database_cleaner gem (3)