为什么factory_girl不是我的事务操作? – 行在testing后保留在数据库中

我试图使用factory_girl来创build一个“用户”工厂(RSpec),但它似乎并没有在事务上运行,显然是因为testing数据库中以前的testing的残留数据而失败。

Factory.define :user do |user| user.name "Joe Blow" user.email "joe@blow.com" user.password 'password' user.password_confirmation 'password' end @user = Factory.create(:user) 

运行第一组testing是好的:

 spec spec/ ... Finished in 2.758806 seconds 60 examples, 0 failures, 11 pending 

一切顺利,如预期的那样,再次运行testing:

 spec spec/ ... /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/validations.rb:1102:in `save_without_dirty!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid) from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/dirty.rb:87:in `save_without_transactions!' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:200:in `save!' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:182:in `transaction' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:200:in `save!' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:208:in `rollback_active_record_state!' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:200:in `save!' from /Library/Ruby/Gems/1.8/gems/factory_girl-1.2.3/lib/factory_girl/proxy/create.rb:6:in `result' from /Library/Ruby/Gems/1.8/gems/factory_girl-1.2.3/lib/factory_girl/factory.rb:316:in `run' from /Library/Ruby/Gems/1.8/gems/factory_girl-1.2.3/lib/factory_girl/factory.rb:260:in `create' from /Users/petenixey/Rails_apps/resample/spec/controllers/users_controller_spec.rb:7 from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_methods.rb:183:in `module_eval' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_methods.rb:183:in `subclass' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_methods.rb:55:in `describe' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_factory.rb:31:in `create_example_group' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/dsl/main.rb:28:in `describe' from /Users/petenixey/Rails_apps/resample/spec/controllers/users_controller_spec.rb:3 from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:147:in `load_without_new_constant_marking' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:147:in `load' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:15:in `load_files' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `each' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `load_files' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/options.rb:133:in `run_examples' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/command_line.rb:9:in `run' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/bin/spec:5 from /usr/bin/spec:19:in `load' from /usr/bin/spec:19 

修复尝试 – 使用Factory.sequence

由于我的电子邮件字段有唯一性约束,我试图通过使用factory_girl的顺序方法来解决这个问题:

 Factory.define :user do |user| user.name "Joe Blow" user.sequence(:email) {|n| "joe#{n}@blow.com" } user.password 'password' user.password_confirmation 'password' end 

我然后跑了

 rake db:test:prepare spec spec/ .. # running the tests once executes fine spec spec/ .. # running them the second time produces the same set of errors as before 

用户似乎仍然在数据库中

如果我查看/db/test.sqlite3数据库,看起来testing用户的行在testing之间没有从数据库回滚。 我认为这些testing应该是事务性的,但对我来说似乎不是这样的。

这将解释为什么testing第一次正确运行(如果我清除了数据库)但第二次失败。

任何人都可以解释我应该改变,以确保testing运行?

最后解决了这个问题,希望我能省下六个小时的debugging时间,让我弄明白了。

通过a)越来越幸运,结束了一个工作的代码版本和b)剥离两套代码,这是我发现:

testing,呛起来

 require 'spec_helper' describe UsersController do @user = Factory.create(:user) end 

testing的工作

 require 'spec_helper' describe UsersController do it "should make a factory models without choking" do @user = Factory.create(:user) end end 

交易是由它“应该做的事情”来定义的。 如果你在该语句之外实例化工厂,事实certificate它不是事务性的。

只要它位于“before..end”块中,您也可以将它放在“it should ..”块之外

 require 'spec_helper' describe UsersController do before(:each) do @user = Factory.create(:user) end it 'should make a factory without choking' do puts @user.name # prints out the correnct name for the user end end 

在实验中,只要在“before..end”块中定义一个“它应该做… end”块之外的用户似乎是有效的。 我想这只是在“它应该do..end”块范围内执行,因此工作正常。

[感谢@jdl的(也是正确的)build议]

请参阅我的博客条目之间的区别使用before :allbefore :each关于交易: http : //mwilden.blogspot.com/2010/11/beware-of-rspecs-before-all.html 。 简而言之, before :all不是事务性的,并且在testing运行之后,在那里创build的数据将会停滞不前。

spec/spec_helper.rb ,确保你有以下

 RSpec.configure do |config| config.use_transactional_fixtures = true end 

这似乎为我解决了这个问题。

test/test_helper.rb里面确保你有以下内容。

 class ActiveSupport::TestCase self.use_transactional_fixtures = true #... end 

尽pipe“fixtures”这个名字也适用于factory_girl

当从Rails 3升级到Rails 4时,我遇到了这些相同的症状。我做了一个bundle安装,开发模式似乎工作正常,但我不会在testing中得到事务行为。 事实certificate,一个包更新解决了这个问题。