Rspec题目!改变前块的 "position"

Rspec subject! alters "position" of a before block

我刚刚在 Rspec 中发现了一些东西(在必要的用头撞墙之后),我希望有人能解释一下。我认为这涉及到我对 Rspec 的 subject!.

的误解

我的理解是,无论是否使用subjectsubject!都会运行主题块,并且该块将在适当的时候得到运行。

似乎发生了什么,只是 - 奇怪的副作用是它会导致 inner subject 块得到 运行 一个内部before块之前。

也就是说:

  describe 'subject block' do
    before { @var = nil }

    describe 'Test 1: With a bang' do
      subject! { @var = false }
      describe 'inner describe' do
        before { @var = true }
        subject { @var }
        it { is_expected.to be true }
      end
    end

    describe 'Test 2: Without a bang' do
      subject { @var = false }
      describe 'inner describe' do
        before { @var = true }
        subject { @var }
        it { is_expected.to be true }
      end
    end
  end

这个结果指出了问题。测试 1,即在外部块中使用 subject! 的测试失败。测试 2 使用非 bang subject 通过。测试 1 失败的原因是放置 @var = true 的内部 before 块未在内部 subject 之前调用,因此未在实际规范之前调用。

这对我来说似乎是错误的。我错过了什么吗?

My understanding is that subject! will run the subject block regardless of whether subject is used, and that block will get run at the appropriate time.

"At the appropriate time" 很含糊,所以这取决于你的意思。 注意 the docs 说的是什么:

Just like subject, except the block is invoked by an implicit before hook.

所以 the implementation subject! 所做的就是委托给 subject,然后定义一个调用主题的 before 挂钩。

当您在多层嵌套中有 before 挂钩时,外部上下文 before 会在内部上下文之前挂钩 运行,正如您所期望的那样。这正是这里发生的事情。

RSpec 的 DSL 在使用得当时非常有用,但它也会混淆事物发生的顺序,当顺序很重要时,我认为你最好将它折叠成一个单个 it 以适当的顺序执行每件事(或者可能为初始的主要设置步骤保留一个 before 挂钩)。