有没有办法用Rspec存根包含模块的方法?

我有一个包含在另一个模块中的模块,它们都实现了相同的方法。 我想存根包含模块的方法,如下所示:

module M def foo :M end end module A class << self include M def foo super end end end describe "trying to stub the included method" do before { allow(M).to receive(:foo).and_return(:bar) } it "should be stubbed when calling M" do expect(M.foo).to eq :bar end it "should be stubbed when calling A" do expect(A.foo).to eq :bar end end 

第一个测试是通过,但第二个测试输出:

 Failure/Error: expect(A.foo).to eq :bar expected: :bar got: :M 

为什么在这种情况下存根不工作? 有没有不同的方法来实现这一目标?

谢谢!

————————————- UPDATE ———— ———————-

谢谢! 使用allow_any_instance_of(M)解决了这个问题。 我的下一个问题是 – 如果我使用prepend而不包括会发生什么? 请参阅以下代码:

 module M def foo super end end module A class << self prepend M def foo :A end end end describe "trying to stub the included method" do before { allow_any_instance_of(M).to receive(:foo).and_return(:bar) } it "should be stubbed when calling A" do expect(A.foo).to eq :bar end end 

这次,使用allow_any_instance_of(M)会导致无限循环。 这是为什么?

注意你不能直接打电话给M.foo ! 你的代码似乎只是起作用,因为你嘲笑M.foo返回:bar

当你打开A元类( class << self )来包含M ,你必须模拟M任何实例,即添加到你的before块:

allow_any_instance_of(M).to receive(:foo).and_return(:bar)

 module M def foo :M end end module A class << self include M def foo super end end end describe "trying to stub the included method" do before do allow(M).to receive(:foo).and_return(:bar) allow_any_instance_of(M).to receive(:foo).and_return(:bar) end it "should be stubbed when calling M" do expect(M.foo).to eq :bar end it "should be stubbed when calling A" do expect(A.foo).to eq :bar end end