为什么 "Do not use `expect` in hooks such as `before`"?

Why "Do not use `expect` in hooks such as `before`"?

标题已经很好地解释了我的问题。我试图 google 它但没有发现任何令人满意的东西。 rubocop-rspec does not allow expect inside before,这是为什么呢?有充分的理由避免这种用法吗?提前感谢您的解释!

只有测试应该包含预期(也称为断言)。 before 块用于配置测试 运行 的环境。它们本身并不是测试。

Four phase test 是单元测试常用的测试模式。一般形式:

test do
  setup
  exercise
  verify
  teardown
end

beforesetup 阶段的一部分,开发人员在该阶段创建场景和支持数据。

expectverify 阶段的一部分,发生在 it 块内。

常见的模式是在 before 块中使用 allow,在 it 块中使用 expect

RSpec.describe User do
  describe '#forgot_password' do
    before { allow(EmailService).to receive(:send) }

    subject { FactoryBot.create(:user).forgot_password }

    it 'sends an email to user to start the password resetting process' do
      subject
      expect(EmailService).to have_received(:send).with(...)
    end
  end
end

before 块也可以添加到应用程序的其他层(spec_helper.rb,共享示例)并且不想依赖块之前的正确顺序来进行测试要成功。

我同意 before 过滤器中的预期,因为您没有更改示例中的任何内容,您总是在测试一般设置,但在 after 过滤器中我没有看到避免的理由期望。

在编写测试时,上下文是最重要的,你是在不同的参数(或上下文)下测试相同的代码,因此,示例只需要修改上下文,而断言可以保持不变。

看这个例子:

 RSpec.describe Foo do
  subject { create(:foo) }

  describe 'some_method' do
    let(:foo) { create(:foo) }

    after do
      foo.update_rate
      subject.update_rate

      expect(foo.rate).to be > subject.rate
    end

    it 'gives higher rates to foos with more reviews if all are positive' do
      foo.update!(votes_up_count: 10, reviews_count: 10)
      subject.update!(votes_up_count: 1, reviews_count: 1)
    end

    it 'gives higher rates to foos with less positive reviews and no negative reviews' do
      foo.update!(votes_up_count: 4, reviews_count: 4)
      subject.update!(votes_up_count: 5, reviews_count: 6)
    end
  end
end

相对于

 RSpec.describe Foo do
  subject { create(:foo) }

  describe 'some_method' do
    let(:foo) { create(:foo) }

    it 'gives higher rates to foos with more reviews if all are positive' do
      foo.update!(votes_up_count: 10, reviews_count: 10)
      subject.update!(votes_up_count: 1, reviews_count: 1)

      foo.update_rate
      subject.update_rate

      expect(foo.rate).to be > subject.rate
    end

    it 'gives higher rates to foos with less positive reviews and no negative reviews' do
      foo.update!(votes_up_count: 4, reviews_count: 4)
      subject.update!(votes_up_count: 5, reviews_count: 6)

      foo.update_rate
      subject.update_rate

      expect(foo.rate).to be > subject.rate
    end
  end
end

所以老实说,我不会把这个警察当作福音,我认为这违背了良好的测试实践。