Joh*_*ash 70 rspec ruby-on-rails
contest_entry_spec.rb
require 'spec_helper'
describe ContestEntry do
before(:all) do
@admission=Factory(:project_admission)
@project=Factory(:project_started, :project_type => @admission.project_type)
@creative=Factory(:approved_creative, :creative_category => @admission.creative_category)
@contest_entry=Factory(:contest_entry, :design_file_name => 'bla bla bla', :owner => @creative, :project => @project)
end
context 'non-specific tests' do
subject { @contest_entry }
it { should belong_to(:owner).class_name('User') }
it { should belong_to(:project) }
it { should have_many(:entry_comments) }
it { should validate_presence_of(:owner) }
it { should validate_presence_of(:project) }
it { should validate_presence_of(:entry_no) }
it { should validate_presence_of(:title) }
end
end
Run Code Online (Sandbox Code Playgroud)
当我运行这些测试时,一切都很好,但是如果我在(:all)之前改变(之前):(每次),每次测试都会失败.我不知道为什么会发生这种情况?
这是错误
Failure/Error: @contest_entry=Factory(:contest_entry, :design_file_name => 'bla bla bla', :owner => @creative, :project => @project)
ActiveRecord::RecordInvalid:
Validation Failed: User is not allowed for this type of project
Run Code Online (Sandbox Code Playgroud)
fon*_*tno 109
before(:all) 在运行所有示例之前运行块一次.
before(:each) 在文件中的每个规范之前运行块一次
before(:all)在运行@admission, @project, @creative, @contest_entry所有it块之前设置实例变量一次.
但是,:before(:each)每次it运行块时,都会重置前块中的实例变量.
它是一个微妙的区别,但很重要
再次,
before(:all)
#before block is run
it { should belong_to(:owner).class_name('User') }
it { should belong_to(:project) }
it { should have_many(:entry_comments) }
it { should validate_presence_of(:owner) }
it { should validate_presence_of(:project) }
it { should validate_presence_of(:entry_no) }
it { should validate_presence_of(:title) }
before(:each)
# before block
it { should belong_to(:owner).class_name('User') }
# before block
it { should belong_to(:project) }
# before block
it { should have_many(:entry_comments) }
# before block
# before block
it { should validate_presence_of(:owner) }
# before block
it { should validate_presence_of(:project) }
# before block
it { should validate_presence_of(:entry_no) }
# before block
it { should validate_presence_of(:title) }
Run Code Online (Sandbox Code Playgroud)
wir*_*d00 31
一个重要的细节before :all是它不是 DB transactional.即,任何内容都before :all存在于数据库中,您必须手动拆除该after :all方法.
含义意味着在测试套件完成后,更改不会为以后的测试做好准备.这可能导致复杂的错误和数据交叉污染的问题.即,如果抛出异常,after :all则不调用回调.
但是,before: each 是 DB事务.
快速测试以证明:
1.截断相应的数据库表然后试试这个,
before :all do
@user = Fabricate(:user, name: 'Yolo')
end
Run Code Online (Sandbox Code Playgroud)
2.之后观察数据库模型仍然存在!
after :all是必须的.但是,如果测试中发生异常,则在流程中断时不会发生此回调.数据库将处于未知状态,这在CI/CD环境和自动测试中尤其成问题.
3.现在试试这个,
before :each do
@user = Fabricate(:user, name: 'Yolo')
end
Run Code Online (Sandbox Code Playgroud)
4.现在,在测试套件完成后,数据库仍然没有数据.测试运行后,我们会更好地保持一致的状态.
简而言之,before :each可能就是你想要的.你的测试运行会稍微慢一些,但这是值得的.
详情请访问:https :
//relishapp.com/rspec/rspec-rails/docs/transactions
请参阅:Data created in before(:all) are not rolled back
希望能帮助另一个疲惫的旅行者.