Rspec:如何在不删减任何内容或在幕后更改任何内容的情况下期待收到的消息

And*_*rew 2 rspec ruby-on-rails rspec-rails

我有一个 Rails 应用程序的 Rspec 测试

  describe '.move_probes_to_master_list' do
    let(:as) { create_list :a, 3, }
    let(:bs) { create_list :b, 3 }

    it 'sums the volumes' do

      active_as= [as[1], as[2]]
      b_ids = [2, 3]
      expect_any_instance_of(A)
        .to receive(:required_volume).twice.with(b_ids)
      expect_any_instance_of(A)
        .to receive(:update_move_to_master_list).twice

      expect(A.calculate_volume(active_as)).to eq(true)
    end
  end
Run Code Online (Sandbox Code Playgroud)

基本上我调用A.calculate_volume并在这个类方法中,我想确保A该类的某个成员也收到一些其他消息。我不想删除这些方法,我希望它们正常运行,但我只想验证是否正在调用这些方法。

这是在循环中运行,所以我不确切知道我将处理哪些实例,但我想确保在某些成员(但不一定两次都必须是同一成员)上调用这两条消息A一共上课两次。

如果我删除expect_any_instance_of(A).to receive期望,一切运行正常并且测试通过。

如果我保留它们,方法调用将失败并且测试中断。

我尝试添加,and_call_original但我觉得我是在黑暗中拍摄,因为文档不清楚这些方法的实际操作方式。

那么如何验证某个类的实例是否在n不更改有关方法调用的其他任何内容的情况下收到消息时间?

我是否错过了在这里收到的期望?我不清楚为什么它首先会存根任何东西。

Gil*_*Him 5

你可以监视这样的方法:

allow(A).to receive(:calculate_volume).and_call_original
Run Code Online (Sandbox Code Playgroud)

然后你可以测试calculate_volume已经被这样调用的:

expect(A).to have_received(:calculate_volume)
Run Code Online (Sandbox Code Playgroud)

这样,原始方法将被调用,并且不会有存根,而是在监视。


and*_*w21 1

我知道这并不能完全回答您的问题“如何继续执行”,但是您应该能够将此测试分为三个不同的测试并创建一组更清晰的测试,而不必担心这样调用原始测试:

describe '.move_probes_to_master_list' do
  let(:as) { create_list :a, 3, }
  let(:active_as) { [as[1], as[2]] }
  let(:bs) { create_list :b, 3 }
  let(:b_ids) { [2, 3] }
  subject { A.calculate_volume(active_as) }

  it 'sums the volumes' do
      expect(subject).to eq(true)
  end

  it 'calls #required_volumen twice' do
    expect_any_instance_of(A)
      .to receive(:required_volume).twice.with(b_ids)
    subject
  end

  it 'calls updates_moves_to_master_list twice' do
    expect_any_instance_of(A)
      .to receive(:update_move_to_master_list).twice
    subject
  end
end
Run Code Online (Sandbox Code Playgroud)