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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24408717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 06:31:18  来源:igfitidea点击:

Is there a way to stub a method of an included module with Rspec?

rubyrspecmixinsstubbing

提问by user3775153

I have a module that is included in another module, and they both implement the same method. I would like to stub the method of the included module, something like this:

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

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

The first test is passing, but the second one outputs:

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

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

   expected: :bar
        got: :M

Why isn't the stub working in this case? Is there a different way to achieve this?

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

Thanks!

谢谢!

-------------------------------------UPDATE----------------------------------

- - - - - - - - - - - - - - - - - - -更新 - - - - - - ---------------

Thanks! using allow_any_instance_of(M) solved this one. My next question is - what happens if I use prepend and not include? see the following code:

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

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 

This time, using allow_any_instance_of(M) results in an infinite loop. why is that?

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

回答by mdemolin

Note you cannot directly call M.foo! Your code only seems to work because you mocked M.footo return :bar.

请注意,您不能直接调用M.foo!您的代码似乎只能工作,因为您嘲笑M.fooreturn :bar

When you open Ametaclass (class << self) to include M, you have to mock any instance of M, that is adding to your beforeblock:

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

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

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