在RSpec中,如何在访问主题的子上下文中添加前挂钩?

时间:2018-03-09 20:17:31

标签: ruby rspec

请考虑以下事项:

describe MyModel do
  context 'updates fields' do
    subject { create(:my_model) }
    before do
      subject.save
      subject.reload
    end

    context 'when changing foo.bar' do
      before { subject.foo.bar = 3 }
      it { is_expected.to be_multiple_bar }
    end

    context 'when changing baz.quux' do
      before { subject.baz.quux = 3 }
      it { is_expected.to be_multiple_quux }
    end
  end
end

现在,正如您所料,我希望在第10行和第15行之后调用第4行的before挂钩

我尝试了两件事:

  1. 我尝试过使用prepend_before,但只有在相同的上下文中定义它们时才有效,它不允许你在一个定义之前添加一个钩子超级语境
  2. 我已尝试在第10行和第15行使用before(:context),虽然这应该按照正确的顺序排列,但RSpec还不允许我在此时改变主题。 (并且有充分的理由,我不想在这里创建共享状态。)
  3. 我真的不想诉诸let(:append_before) { proc { #magic here } },因为它很丑陋和黑客一样。此外,我认为我想要的是完全合理的。现在我将这两行复制到所有子上下文中,我对此并不满意。

    有什么更好的方法可以做到这一点?

    我正在使用RSpec 3.7,FactoryGirl 4.8.0和Ruby 2.3.1

1 个答案:

答案 0 :(得分:-1)

我不知道你的工厂是什么样的,但是要创建和持久化my_model,修改,保存和重新加载它,你应该只创建一次。这也将加快您的规格。

你可以这样写:

describe MyModel do
  context 'updates fields' do
    subject { create(:my_model, foo: {bar: bar}, baz: {quux: quux}) }

    context 'when changing foo.bar' do
      let(:bar) { 3 }
      it { is_expected.to be_multiple_bar }
    end

    context 'when changing baz.quux' do
      let(:quux) { 3 }
      it { is_expected.to be_multiple_quux }
    end
  end
end

对let和subject进行惰性评估可确保根据上下文正确设置所有参数。如果您需要/想要扩展工厂以支持它,请查看http://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md

我希望这是有道理的。