Pet*_*xey 34 ruby-on-rails factory-bot
我正在尝试使用factory_girl创建一个"用户"工厂(使用RSpec)但是它似乎没有在事务上运行,并且由于测试数据库中先前测试的残余数据而显然失败了.
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)
Run Code Online (Sandbox Code Playgroud)
运行第一组测试很好:
spec spec/
...
Finished in 2.758806 seconds
60 examples, 0 failures, 11 pending
Run Code Online (Sandbox Code Playgroud)
一切都很好并且符合预期,但是再次运行测试:
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
Run Code Online (Sandbox Code Playgroud)
修复尝试 - 使用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
Run Code Online (Sandbox Code Playgroud)
然后我跑了
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
Run Code Online (Sandbox Code Playgroud)
用户似乎仍留在数据库中
如果我查看/db/test.sqlite3数据库,似乎测试用户的行没有在测试之间从数据库回滚.我认为这些测试应该是交易性的,但对我来说似乎并非如此.
这可以解释为什么测试第一次正确运行(如果我清除数据库)但第二次失败.
谁能解释我应该改变什么以确保测试以事务方式运行?
Pet*_*xey 52
最后解决这个问题,我希望我可以节省六个小时的调试时间,这让我想出来了.
通过a)变得幸运并最终得到一个有效的代码版本和b)剥离这两组代码,这就是我发现的:
测试窒息
require 'spec_helper'
describe UsersController do
@user = Factory.create(:user)
end
Run Code Online (Sandbox Code Playgroud)
测试有效
require 'spec_helper'
describe UsersController do
it "should make a factory models without choking" do
@user = Factory.create(:user)
end
end
Run Code Online (Sandbox Code Playgroud)
该事务由它"应该做某事"做...声明.如果您在该声明之外实例化工厂,则结果不是事务性的.
你也可以将它放在"it should .."块之外,只要它在"before..end"块中
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
Run Code Online (Sandbox Code Playgroud)
在实验中,只要它在"before ... end"块中,在"it should do..end"块之外定义用户似乎是有效的.我想这只是在"it should do..end"块的范围内执行,因此工作正常.
[感谢@jdl提出的(也是正确的)建议]
Mar*_*den 21
请参阅我的博客文章,了解使用before :all和before :each关于交易的区别:http://mwilden.blogspot.com/2010/11/beware-of-rspecs-before-all.html.简而言之,before :all不是事务性的,并且在测试运行后,在那里创建的数据将会存在.
| 归档时间: |
|
| 查看次数: |
11023 次 |
| 最近记录: |