2015-10-06 113 views
2

在替換原始模擬方法之前,有沒有一種方法可以在每次期望中只模擬一次方法一次?只模擬一次方法

我覺得像這樣的工作(注意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

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

回答

4

這可能有點不直觀,但你可以通過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