Factory Girl / Capybara正在从数据库中期测试中删除记录? [英] Factory Girl / Capybara deleting records from database mid-test?

查看:62
本文介绍了Factory Girl / Capybara正在从数据库中期测试中删除记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与RSpec&水豚,我得到了一个有趣的测试失败模式,该模式通过在测试用例中对行进行一些细微的重排而消失了……这无关紧要。

Working with RSpec & Capybara, I'm getting an interesting test failure mode which goes away with a few subtle rearrangements of lines in the test case...stuff that shouldn't matter.

我正在开发自己的身份验证系统。它目前正在运行,我可以使用浏览器登录/注销,会话也可以运行,等等。但是,尝试测试失败。发生的事情我不太了解,这似乎取决于(看似)不相关的呼叫的顺序。

I'm developing my own authentication system. It is currently working and I can login/out with the browser and the session works etc etc. However, trying to test this is failing. Something is going on that I don't quite understand, which seems to depend on the order of (seemingly) unrelated calls.

require 'spec_helper'

describe "Sessions" do
  it 'allows user to login' do
    #line one
    user = Factory(:user)
    #For SO, this method hashes the input password and saves the record
    user.password! '2468'

    #line two
    visit '/sessions/index'


    fill_in 'Email', :with => user.email
    fill_in 'Password', :with => '2468'
    click_button 'Sign in'

    page.should have_content('Logged in')
  end
end

按原样,该测试失败...登录失败。在规范和控制器中都插入了 debugger调用之后,我可以看到原因:就控制器而言,用户并没有插入数据库:

As is, that test fails...the login fails. After inserting 'debugger' calls into both the spec and the controller I can see why: the user is not getting inserted into the database as far as the controller is concerned:

编辑在ApplicationController中添加

Edit adding in ApplicationController

class ApplicationController < ActionController::Base
  helper :all
  protect_from_forgery

  helper_method :user_signed_in?, :guest_user?, :current_user

  def user_signed_in?
    !(session[:user_id].nil? || current_user.new_record?)
  end

  def guest_user?
    current_user.new_record?
  end

  def current_user
    @current_user ||= session[:user_id].nil? ? User.new : User.find(session[:user_id])
  rescue ActiveRecord::RecordNotFound
    @current_user = User.new
    flash[:notice] = 'You\'ve been logged out.'
  end
end


class SessionsController < ApplicationController
  def login
    user = User.where(:email=>params[:user][:email]).first

    debugger ###

    if !user.nil? && user.valid_password?(params[:user][:password])
      #engage session
    else
      #run away
    end
  end

  def logout
    reset_session
    redirect_to root_path, :notice => 'Logget Out.'
  end
end

在控制台中,高于断点:

in the console, at the above breakpoint:

1.9.2 vox@Alpha:~/Sites/website$ rspec spec/controllers/sessions_controller_spec.rb 
/Users/vox/Sites/website/app/controllers/sessions_controller.rb:7
if !user.nil? && user.valid_password?(params[:user][:password])
(rdb:1) irb
ruby-1.9.2-p180 :001 > User.all.count
 => 0 
ruby-1.9.2-p180 :002 > 

但是,如果我重新排列测试中的几行,则将 2行放在 1行之上':

However, if I rearrange a few lines in my test, putting line 'two' above line 'one':

describe "Sessions" do
  it 'allows user to login' do
    #line two
    visit '/sessions/index'

    #line one
    user = Factory(:user)
    #For SO, this method hashes the input password and saves the record
    user.password! '2468'


    fill_in 'Email', :with => user.email
    fill_in 'Password', :with => '2468'
    click_button 'Sign in'

    page.should have_content('Logged in')
  end
end

我在控制台中得到了(与上面相同的断点):

I get this in the console (same breakpoint as above):

1.9.2 vox@Alpha:~/Sites/website$ rspec spec/controllers/sessions_controller_spec.rb 
/Users/vox/Sites/website/app/controllers/sessions_controller.rb:7
if !user.nil? && user.valid_password?(params[:user][:password])
(rdb:1) irb
ruby-1.9.2-p180 :001 > User.all.count
 => 1 

为了简洁起见,我省略了用户对象内容的全部转储,但是我可以向您保证测试会按预期完成。

For the sake of brevity I've omitted the full dump of the contents of the user object but I can assure you that the test completes as expected.

这种换行以使测试通过的行为与我的想法应该不太吻合。继续执行这些命令,事实证明,这对我在其他领域的测试相当有利。

This behavior of swapping lines to get the test to pass doesn't really fit well with my idea of what should be going on with these commands and has proven to be quite a bear to my testing in other areas.

有什么提示吗?

我已经谷歌和SO搜寻提出此问题的想法,并且不乏有关RSpec / Capybara和Sessions的SO问题。

I've scoured google and SO for ideas which present this problem, and there are no shortage of SO questions about RSpec/Capybara and Sessions. Nothing seemed to fit quite right though.

感谢您的查找。

更新

我在测试中添加了一个断点(恰好在拜访电话之前)并进行了一些调试,然后返回:

I've added a breakpoint (just before a visit call) and some debugging to the test and come back with this:

(rdb:1) user
#<User id: 1, login_count: 1, email: "testuser1@website.com", encrypted_password: "11f40764d011926eccd5a102c532a2b469d8e71249f3c6e2f8b...", salt: "1313613794">
(rdb:1) User.all
[#<User id: 1, login_count: 1, email: "testuser1@website.com", encrypted_password: "11f40764d011926eccd5a102c532a2b469d8e71249f3c6e2f8b...", salt: "1313613794">]
(rdb:1) next
/Users/vox/Sites/website/spec/controllers/sessions_controller_spec.rb:19
fill_in 'Email', :with => user.email
(rdb:1) User.all
[]

显然,访问过程中的某些事情是告诉Factory Girl它已经完成了对用户对象的操作,因此她将其删除了?

So clearly something along the way that visit does is telling Factory Girl that its done with the user object and so she deletes it?

编辑仔细检查test.log,没有发出任何删除。因此,我或多或少回到了第一个问题。

Edit After inspecting test.log carefully, nothing is issuing any delete. So I'm more or less back to square one.

推荐答案

借助Factory Girl邮件列表,我发现了

With the help of the Factory Girl mailing list I've found the issue.

默认情况下,RSpec使用事务将数据库保持在干净状态,并且每个事务都与一个线程绑定。沿管道的某个位置,visit_page命令分离,与当前线程绑定的事务消亡。

By default RSpec uses transactions to maintain the database in a clean state and each transaction is tied to a thread. Somewhere along the pipeline the visit_page command splits off and the transaction tied to the current thread dies.

解决方案很简单:禁用事务。

The solution is simple: disable transactions.

describe "Sessions" do
  self.use_transactional_fixtures = false

   it 'no longer uses transactions' do
     #whatever you want
  end
end

Rails 5.1更新

从Rails 5.1开始, use_transactional_fixtures 已过时,应替换为 use_transactional_tests

As of Rails 5.1, use_transactional_fixtures is deprecated and should be replaced with use_transactional_tests.

self.use_transactional_tests = false

这篇关于Factory Girl / Capybara正在从数据库中期测试中删除记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆