Подтвердить что ты не робот

В RSpec существует метод, эквивалентный "unub", но для "should_receive"?

Есть ли какой-либо метод для удаления любых stubbing и насмешек при использовании RSpec?

Пример:

RestClient.should_receive(:delete).with("http://www.example.com")
...
... 

# this will remove the mocking of "should_receive" and 
# restore the proper "delete" method on "RestClient".
RestClient.mocking_reset

(mocking_reset - мое фиктивное имя для требуемой функциональности).

Я знаю, что существует метод "unub", который сбрасывает "заглушки", но не "should_receive" s.

Итак, есть ли какой-либо метод, эквивалентный "unub", но для "should_receive"?

Панайотис

4b9b3361

Ответ 1

В настоящий момент (rspec-mocks 2.10.1) нет метода, эквивалентного unstub, но для should_receive. Вы можете reset все заглушки и макеты с помощью rspec_reset, и вы также можете писать грязные хаки, чтобы удалить определенное ожидание (которое я бы не рекомендовал).

Ниже приведен пример удаления всех заглушек и ожиданий объекта:

describe "resetting stubs and expectations with rspec_reset" do
  before do
    @person = mock('person')
    @person.should_receive(:poke)
  end

  it "should not fail when we reset all stubs and expectations" do
    @person.rspec_reset
  end
end

Обратите внимание, что этот метод аннотируется в исходном коде rspec как @private, что означает, что вам следует избегать его использования более чем абсолютно необходимо, и он может нарушать в будущих версиях rspec без предупреждения. Это, однако, довольно широко используется в спецификациях для самого rspec, поэтому представляется менее вероятным, что это будет устаревшим в ближайшее время.

После копания кода rspec-mocks немного больше, вы можете, конечно, сделать что-то действительно неприятное и вырвать одно конкретное ожидание:

# Works in rspec 2.10.1
describe "removing an expectation with an ugly hack" do
  before do
    @person = mock('person')
    @person.should_receive(:poke)
  end

  it "should not fail after we hack rspec by violating every law of good programming, ever" do
    @person.instance_variable_get(:@mock_proxy).instance_variable_get(:@method_double)[:poke].clear
  end
end

Это действительно плохо, так как это нарушает инкапсуляцию тестового пакета rspec, и вы не должны этого делать. Вместо этого, если у вас действительно была веская причина удалить определенное ожидание, правильным было бы добавить открытый метод вверх по течению в rspec-mocks, который добавит параллельный метод к unstub, но для устранения определенных ожиданий. Вероятно, он находится здесь (обратите внимание на определение stub и unstub, а также в этом файле):

https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/methods.rb

Перед тем, как выйти и использовать любое из приведенных выше предложений для устранения ожидаемого ожидания, вы можете подумать, действительно ли ваши спецификации действительно должны это сделать или если они должны быть реорганизованы. Использование should_receive - это утверждение о вашем коде, и обычно вам следует попытаться создать примеры (т.е. it blocks), которые утверждают только одно. Мне было бы очень интересно, почему вам нужно что-то вроде rspec_reset, если вы не пытаетесь сделать слишком много в глобальной настройке (например, before :each или до: все блоки), или если ваши примеры пытаются сделать слишком много (т.е. с несколькими утверждениями в одном примере).

Единственное исключение из этого может быть, конечно, в наборе тестов rspec-mocks, где rspec_reset используется для состояния reset между примерами, которые проверяют функциональность применения заглушек и mocks. Если вы этого не сделаете, скорее всего, ваши тесты могут быть улучшены, чтобы не полагаться на глобальные сбросы заглушек и mocks на объект.

Я надеюсь, что это поможет и, пожалуйста, сообщите мне, если вы считаете, что существует законный случай добавления эквивалентного метода к unstub, а для ожиданий сообщений (т.е. после использования should_receive). Если я убежден, что это нормально, я бы хотел добавить этот метод и предложить его добавить вверх по течению. Может быть, это называется unset_expectation? Пожалуйста, также не стесняйтесь использовать руководство для кода и внутренних структур выше, чтобы собрать запрос на вытягивание для rspec-mocks самостоятельно, и мы увидим, принимается ли он, чтобы создать насмешливый эквивалент unstub.

Ответ 2

Вы можете перезаписать предыдущее издевательство:

expect(RestClient).to receive(:delete).and_call_original

Или, если это было не какое-то ожидание, просто простая заглушка:

allow(RestClient).to receive(:delete).and_call_original

Помните, что существует также expect_any_instance_of и allow_any_instance_of.

Ответ 3

Для RSpec >= 2.14 принятый ответ больше не будет работать. Я отсылаю вас к Bernhard Köhler ответу на эту тему (воспроизведено ниже, чтобы защитить от гниения ссылки): undefined метод` rspec_reset 'с rspec версии 2.14

Метод reset не существует в RSpec 2.14. Вместо этого это помощник метод, определенный внутри файла spec_helper.rb для rspec-mocks проект.

module VerifyAndResetHelpers
  def verify(object)
    RSpec::Mocks.proxy_for(object).verify
  end

  def reset(object)
    RSpec::Mocks.proxy_for(object).reset
  end
end

Вы можете видеть, что этот метод делегирует действие reset для базового прокси вместо того, чтобы использовать его для определения класса объект, о котором идет речь.