Ruby on rails rails rspec在所有之前vs在每个之前

Ruby on rails rails rspec在所有之前vs在每个之前,ruby-on-rails,rspec,Ruby On Rails,Rspec,竞赛项目\u规格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

竞赛项目\u规格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
当我运行这些测试时,一切都正常,但是如果我将before(:all)更改为before(:each),每个测试都会失败。我不知道为什么会发生这种情况

这就是错误所在

 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
before(:all)
在运行所有示例之前运行块一次

before(:each)
在文件中的每个规格之前运行块一次

before(:all)
在运行所有
it
块之前,将实例变量
@admission、@project、@creative、@contest\u entry
设置一次

但是,
:before(:each)
在每次运行
it
块时重置before块中的实例变量

这是一个微妙的区别,但很重要

再说一遍

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) }

before(:all)
,它确保在块中的所有测试之前创建一次示例用户。这是对速度的优化。

之前的
的一个重要细节:所有的
都是而不是DB
事务性的
。也就是说,
before:all
中的任何内容都会保留到数据库中,您必须在
after:all
方法中手动拆除

这意味着,在测试套件完成之后,更改不会恢复为以后的测试做好准备。这可能导致复杂的错误和数据交叉污染问题。也就是说,如果抛出异常,则不会调用
after:all
回调

但是,
before:每个
都是DB事务

演示的快速测试:

1。截断相应的DB表,然后尝试此操作

  before :all do
    @user = Fabricate(:user, name: 'Yolo')
  end
  before :each do
    @user = Fabricate(:user, name: 'Yolo')
  end
2.事后观察数据库模型保持不变

after:all
是必需的。但是,如果测试中发生异常,则此回调不会发生,因为流被中断。数据库将处于未知状态,这对于CI/CD环境和自动化测试来说尤其有问题

3.现在试试这个

  before :all do
    @user = Fabricate(:user, name: 'Yolo')
  end
  before :each do
    @user = Fabricate(:user, name: 'Yolo')
  end
4.现在测试套件完成后,数据库仍然没有数据。更好,让我们在测试运行后保持一致的状态

简而言之,
before:each
,可能就是您想要的。您的测试运行会稍微慢一点,但这是值得的

详情如下: 请参阅:
before(:all)中创建的数据不会回滚


希望这能帮助另一位疲惫的旅行者。

需要注意的一点是,默认情况下,在使用前(:each),在使用前(:all)中,控制器实例未设置,因此控制器方法(如请求)未使用。

此提示节省我的时间!你知道为什么用before(:each)失败了吗