Вопрос по ruby-on-rails-3, ruby-on-rails – Невозможно заглушить вспомогательный метод с помощью rspec

21

Я пытаюсь заглушить метод на помощник, который определен в моем контроллере. Например:

class ApplicationController < ActionController::Base
  def current_user
    @current_user ||= authenticated_user_method
  end
  helper_method :current_user
end

module SomeHelper
  def do_something
    current_user.call_a_method
  end
end

В моем Rspec:

describe SomeHelper
  it "why cant i stub a helper method?!" do
    helper.stub!(:current_user).and_return(@user)
    helper.respond_to?(:current_user).should be_true # Fails
    helper.do_something # Fails 'no method current_user'
  end
end

Вspec/support/authentication.rb

module RspecAuthentication
  def sign_in(user)
    controller.stub!(:current_user).and_return(user)
    controller.stub!(:authenticate!).and_return(true)

    helper.stub(:current_user).and_return(user) if respond_to?(:helper)
  end
end

RSpec.configure do |config|
  config.include RspecAuthentication, :type => :controller
  config.include RspecAuthentication, :type => :view
  config.include RspecAuthentication, :type => :helper
end

Я задал похожий вопросВот, но остановился на работе вокруг. Это странное поведение снова закралось, и я хотел бы понять,why это не работает.

UPDATE: Я нашел это призваниеcontroller.stub!(:current_user).and_return(@user) доhelper.stub!(...) это то, что вызывает такое поведение. Это достаточно легко исправить вspec/support/authentication.rb, но это ошибка в Rspec? Я не понимаю, почему можно было бы ожидать, что он не сможет заглушить метод на помощнике, если он уже заглушен на контроллере.

Похоже, ошибка. Стоит подать вопрос наgithub.com/rspec/rspec-mocks/issues (и пытается с последней версией). Rob Davis
Создан тикет:github.com/rspec/rspec-mocks/issues/135 Brad
Попробуйте заглушить метод через ApplicationController, поскольку именно там он определен.ApplicationController.stub(:current_user => @user) РЕДАКТИРОВАТЬ: Теперь я думаю, что это может не сработать. dwhalen
У меня та же проблема, есть ли какие-либо решения еще? ajahongir
Нет, это не сработало. Я старалсяany_instance тоже без удачи. Я на самом деле получил это работает, но я немного запутался (возможно, нашел ошибку с rspec). Я обновлю вопрос в ближайшее время. Brad

Ваш Ответ

4   ответа
20

Обновление ответа Мэтью Ратцлоффа: вам не нужен экземпляр объекта и заглушка! устарел

it "why can't I stub a helper method?!" do
  helper.stub(:current_user) { user }
  expect(helper.do_something).to eq 'something'
end

Редактировать. RSpec 3 способstub! было бы:

allow(helper).to receive(:current_user) { user }

Увидеть:https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/

Я исправил свой ответ для RSpec 3.
это не работает.
8

Попробуйте это, у меня получилось:

describe SomeHelper
  before :each do
    @helper = Object.new.extend SomeHelper
  end

  it "why cant i stub a helper method?!" do
    @helper.stub!(:current_user).and_return(@user)
    # ...
  end
end

Первая часть основана наэтот ответ автором RSpec, а вторая часть основана наэтот ответ переполнения стека.

это не работает
... а затем тесты должны проверять @helper, а не SomeHelper.
3

В RSpec 3.5 RSpec вроде быhelper больше не доступен изit блок. (Это даст вам следующее сообщение:

helper is not available from within an example (e.g. an it block) or from constructs that run in the scope of an example (e.g. before, let, etc). It is only available on an example group (e.g. a describe or context block).

(Кажется, я не могу найти какую-либо документацию по этому изменению, это все знания, полученные экспериментально).

Ключом к решению этой проблемы является знание того, что вспомогательные методы являются методами экземпляра, и что для ваших собственных вспомогательных методов это легко сделать:

allow_any_instance_of( SomeHelper ).to receive(:current_user).and_return(user) 

Это то, что, наконец, работает для меня

Сноски / Кредит Где Кредит должен:

3

Rspec 3

  user = double(image: urlurl)
  allow(helper).to receive(:current_user).and_return(user)
  expect(helper.get_user_header).to eq("/uploads/user/1/logo.png")

Похожие вопросы