只模拟一次方法

问题描述:

在替换原始模拟方法之前,有没有一种方法可以在每次期望中只模拟一次方法一次?只模拟一次方法

我觉得像这样的工作(注意once

class Klass 
    def self.meth 
     'baz' 
    end 
end 

describe Klass do 
    subject{ described_class.meth } 
    before{ allow(described_class).to receive(:meth).once.and_return('foo') } 
    it{ is_expected.to eq 'foo' } 
    context 'throwing in a context just to test' do 
     it{ is_expected.to eq 'foo' } 
     it{ is_expected.to eq 'foo' } 
     it{ is_expected.to eq 'foo' } 
     it 'only mocks once' do 
      expect(subject).to eq 'foo' 
      expect(subject).to eq 'baz' # this is the key 
     end # pass 
    end 
end 

不幸的是我得到这个错误:

(Klass (class)).meth(no args) 
     expected: 1 time with any arguments 
     received: 2 times 

我本来预期已经得到了失败,如果我说expect(Klass).to receive(:meth).once而比较宽松的allow

我想知道我怎样才能嘲笑一次和每期望一次。

这可能有点不直观,但你可以通过specifying different return values for multiple callsKlass.meth来做到这一点。

在你的情况,你可以用'foo'存根Klass.meth第一个呼叫,然后存根每隔调用Klass.meth原来实行的方法。这看起来是这样的:

allow(described_class).to receive(:meth).and_return('foo', described_class.meth)

我们需要在您的测试是在最后的测试不使用subject改变,因为它是memoising返回值时Klass.meth被称为第一次接下来的事情(这就是为什么所有使用subject的其他测试仍会通过),因此测试中的第二个期望失败。相反,我们可以直接在每个规范中调用该方法:

class Klass 
    def self.meth 
    'baz' 
    end 
end 

describe Klass do 
    subject { described_class.meth } 

    before do 
    allow(described_class).to \ 
     receive(:meth).and_return('foo', described_class.meth) 
    end 

    it { is_expected.to eq 'foo' } 

    context 'throwing in a context just to test' do 
    it { is_expected.to eq 'foo' } 
    it { is_expected.to eq 'foo' } 
    it { is_expected.to eq 'foo' } 

    it 'only mocks once' do 
     expect(described_class.meth).to eq 'foo' 
     expect(described_class.meth).to eq 'baz' 
    end # pass 
    end 
end