为什么在 RSpec 中改变 'it' 和 'subject' 的顺序会改变我的测试结果?

Why does changing the order of 'it' and 'subject' in RSpec change my test result?

正在测试的classqa.rb包含代码:

class QA
  def initialize(bugs: 0)
    @bugs = bugs
  end

  def speak
    "Hello!"
  end

  def happy?
    @bugs > 0
  end

  def debug
    @bugs = 0
  end
end

RSpec 文件 qa_spec.rb 包含代码:

require 'rspec'
require_relative 'qa'

RSpec.describe QA do
  describe '#happy?' do
    context 'when bugs are more than 0' do
      it 'returns true' do
        subject { described_class.new(bugs: 1) }
        expect(subject).to be_happy
      end
    end
  end
end
    

当我 运行 时测试失败,并给我这个错误:

PS C:\Users\Jobla\repos\TDD> rspec qa_spec.rb
F

Failures:

  1) QA#happy? when bugs are more than 0 returns true
     Failure/Error: expect(subject).to be_happy
       expected `#<QA:0x2e0d640 @bugs=0>.happy?` to return true, got false
     # ./qa_spec.rb:9:in `block (4 levels) in <top (required)>'

Finished in 0.02999 seconds (files took 0.16995 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./qa_spec.rb:7 # QA#happy? when bugs are more than 0 returns true

但是,当我编辑 qa_spec.rb 并交换 itsubject 行时,测试突然通过了:

require 'rspec'
require_relative 'qa'

RSpec.describe QA do
  describe '#happy?' do
    context 'when bugs are more than 0' do      
      subject { described_class.new(bugs: 1) }  #swapped with line below 
      it 'returns true' do                      #swapped with line above
        expect(subject).to be_happy
      end
    end
  end
end

测试通过:

PS C:\Users\Jobla\repos\TDD> rspec qa_spec.rb
.

Finished in 0.01003 seconds (files took 0.17993 seconds to load)
1 example, 0 failures

请有人解释一下 为什么交换 itsubject 行会改变测试结果?

subject 设计为在 contextdescribe 块中设置,而不是在 it 中设置。 如果您没有在 it 之前设置 subject,那么 subject 将通过在 described_class 上不带参数调用 new 来自动设置。 bugs 将设置为默认值 0。之后,你在it里面用一个块subject { described_class.new(bugs: 1) }来调用它,它和你调用described_class.new { described_class.new(bugs: 1) }是一样的,因为it里面的subject是[的一个实例=26=] class.