RSpec:如何仅存根对同一方法的多次调用中的一个

dor*_*emi 2 ruby unit-testing rspec

我无法弄清楚如何仅存根对方法的两次调用中的一个。下面是一个例子:

class Example
  def self.foo
    { a: YAML.load_file('a.txt'),   # don't stub - let it load
      b: YAML.load_file('b.txt') }  # stub this one
  end
end

RSpec.describe Example do
  describe '.foo' do
    before do
      allow(YAML).to receive(:load_file).with('b.txt').and_return('b_data')
    end

    it 'returns correct hash' do
      expect(described_class.foo).to eq(a: 'a_data', b: 'b_data')
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

测试失败,因为我已经YAML.load_file用参数为第二个调用 ( 'b.txt') 而不是它遇到的第一个调用 ( )存根了一个调用'a.txt'。我认为参数匹配可以解决这个问题,但事实并非如此。

Failures:

  1) Example.foo returns correct hash
     Failure/Error:
       { a: YAML.load_file('a.txt'),
         b: YAML.load_file('b.txt') }

       Psych received :load_file with unexpected arguments
         expected: ("b.txt")
              got: ("a.txt")
        Please stub a default value first if message might be received with other args as well.  
Run Code Online (Sandbox Code Playgroud)

有没有办法允许第一个呼叫YAML.load_file通过但只存根第二个呼叫?我该怎么做?

per*_*won 9

有一个and_call_original选项(请参阅rspec 文档)。

应用于您的示例,这应该可以满足您的要求:

before do
  allow(YAML).to receive(:load_file).and_call_original
  allow(YAML).to receive(:load_file).with('b.txt').and_return('b_data')
end
Run Code Online (Sandbox Code Playgroud)