Rails rspec #<RSpec::ExampleGroups:: 的未定义方法“接收”

Rails rspec undefined method `receive' for #<RSpec::ExampleGroups::

我想测试一些实例没有接收到特定的方法调用。正在尝试

RSpec.describe 'something' do
  before { subject.stubs(foo: 'bar') }
  it { is_expected.to_not receive(:foo) }
end

给我

Failure/Error: it { is_expected.to_not receive(:foo) }

NoMethodError:
  undefined method `receive' for #<RSpec::ExampleGroups::Something:0x0000000010391588>

并努力

RSpec.describe 'something else' do
  before { subject.stubs(foo: 42) }
  it { subject.expects(:foo).never; subject.foo }
end

通过。我做错了什么?

我被 Rails rspec undefined method `receive_message' for #<RSpec::ExampleGroups:: 引导到当前无效的解决方案,我正在使用

RSpec 3.7
  - rspec-core 3.7.1
  - rspec-expectations 3.7.0
  - rspec-mocks 3.7.0
  - rspec-support 3.7.1

更新 1:我正在使用 webmock 而不是 rspec-mocks

更新 2:我正在使用 webmockmocha

更新 3:感谢所有的解释,@engineersmnky!不幸的是,对于我的特定用例,我仍然需要存根该方法。为什么这个还是通过了?

require 'rspec'
require 'mocha'

RSpec.configure do |config|
  config.mock_with :mocha
end

RSpec.describe 'something' do
  # passes
  it 'can hide from foo' do 
    subject.stubs(:foo)
    expects(:foo).never
    subject.foo
  end
end

区别在于我试图表达我希望信号:foo永远不会被发送。

好的,这里有 2 个问题。首先是您尝试使用 rspec 期望语法和 mocha 作为您的模拟框架。这导致:

undefined method `receive' for #<RSpec::ExampleGroups::Something:0x0000000010391588>

错误,因为 mocha 不知道 receivemocha 的语法应该是:

it { expects(:foo).never }  

您的下一个问题是 before 块正在存根 foo 因此它从未真正到达接收器。所以你的第二种情况通过了,因为 subject 从未真正收到 foo 因为存根拦截了调用。

示例:

require 'rspec'
require 'mocha'

RSpec.configure do |config|
  config.mock_with :mocha
end

def stub_obj(obj,method_list)
  Class.new(SimpleDelegator) do 
      method_list.each do |k,v| 
          define_method(k) {v}
      end
  end.new(obj)
end

RSpec.describe 'something' do

  subject {mock('subject')}
  #passes 
  it { expects(:foo).never }
  # fails 
  it { subject.expects(:foo).never; subject.foo }
  # passes 
  it 'can hide from foo' do 
    subject.stubs(:foo)
    subject.expects(:foo).never
    subject.foo
  end

  context 'kind of like this' do
    # passes
    it 'hides with a stubbed method' do
      stubber = stub_obj(subject, foo: 'bar')
      subject.expects(:foo).never
      stubber.foo
    end
    # fails 
    it 'cannot hide from a non-stubbed method' do
      stubber = stub_obj(subject, foo: 'bar')
      subject.expects(:bar).never
      stubber.bar
    end
  end
end

如果您有兴趣,这里是 Object#stubs 的实现,虽然它通过 Mocha::Mockery 对象比我的示例 (#stub_obj) 做的多一点,但概念是相同的。