Rails rspec неопределенный метод `receive 'для # <RSpec :: ExampleGroups :: - PullRequest
0 голосов
/ 30 апреля 2018

Я хочу проверить, что некоторый экземпляр не получает определенный вызов метода. Пытаясь

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 неопределенный метод `receive_message 'для # , и я использую

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: я использую webmock и mocha.

Обновление 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 никогда не будет отправлен.

1 Ответ

0 голосов
/ 30 апреля 2018

Хорошо, здесь есть 2 проблемы. Во-первых, вы пытаетесь использовать синтаксис ожиданий rspec с mocha в качестве фреймворка. Это вызывает:

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

Ошибка, поскольку mocha не знает о receive. Синтаксис для mocha должен быть:

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, если вам интересно, и хотя она делает немного больше, чем мой пример (#stub_obj) через Mocha::Mockery объект, концепция та же.

...