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

Как заглушить метод ApplicationController в спецификации запроса

Мне нужно заглушить ответ метода current_user в спецификации запроса Rspec/capybara. Метод определен в ApplicationController и использует helper_method. Метод должен просто вернуть идентификатор пользователя. В рамках теста я хотел бы, чтобы этот метод возвращал один и тот же идентификатор пользователя каждый раз.

В качестве альтернативы я мог бы исправить свою проблему, установив session[:user_id] в spec (что возвращает current_user)... но это тоже не работает.

Возможны ли какие-либо из этих вариантов?

Edit:

Вот что я получил (он не работает, он просто запускает обычный метод current_user).

require 'spec_helper'

describe "Login" do

   before(:each) do
     ApplicationController.stub(:current_user).and_return(User.first)
   end

  it "logs in" do
    visit '/'
    page.should have_content("Hey there user!")
  end

end

Также не работает:

require 'spec_helper'

describe "Login" do

  before(:each) do
    @mock_controller = mock("ApplicationController") 
    @mock_controller.stub(:current_user).and_return(User.first)
  end

  it "logs in" do
    visit '/'
    page.should have_content("Hey there user!")
  end

end
4b9b3361

Ответ 1

skalee, похоже, дал правильный ответ в комментарии.

Если метод, который вы пытаетесь заглушить, является методом экземпляра (скорее всего), а не методом класса, то вам нужно использовать:

ApplicationController.any_instance.stub(:current_user)

Ответ 2

Вот несколько примеров базовой формы.

controller.stub(:action_name).and_raise([some error])
controller.stub(:action_name).and_return([some value])

В вашем конкретном случае я считаю, что правильная форма:

controller.stub(:current_user).and_return([your user object/id])

Вот полный рабочий пример проекта, над которым я работаю:

describe PortalsController do

  it "if an ActionController::InvalidAuthenticityToken is raised the user should be redirected to login" do
    controller.stub(:index).and_raise(ActionController::InvalidAuthenticityToken)
    get :index
    flash[:notice].should eql("Your session has expired.")
    response.should redirect_to(portals_path)
  end

end

Чтобы объяснить мой полный пример, в основном это означает, что при возникновении ошибки ActionController::InvalidAuthenticityToken в любом месте приложения появляется сообщение со вспышкой, и пользователь перенаправляется на действие portals_controller#index. Вы можете использовать эти формы для вывода и возврата определенных значений, проверки экземпляра заданной ошибки и т.д. Существует несколько доступных методов .stub(:action_name).and_[do_something_interesting]().


Обновить (после добавления кода): за мой комментарий измените свой код, чтобы он читал:

require 'spec_helper'

describe "Login" do

   before(:each) do
      @mock_controller = mock("ApplicationController") 
      @mock_controller.stub(:current_user).and_return(User.first)
   end

  it "logs in" do
    visit '/'
    page.should have_content("Hey there user!")
  end

end

Ответ 3

Это работает для меня и дает мне переменную @current_user для использования в тестах.

У меня есть помощник, который выглядит так:

def bypass_authentication
  current_user = FactoryGirl.create(:user)

  ApplicationController.send(:alias_method, :old_current_user, :current_user)
  ApplicationController.send(:define_method, :current_user) do 
    current_user
  end
  @current_user = current_user
end

def restore_authentication
  ApplicationController.send(:alias_method, :current_user, :old_current_user)
end

И затем в моих запросах спецификации я вызываю:

before(:each){bypass_authentication}
after(:each){restore_authentication}

Ответ 4

Для тех, кому, возможно, понадобится заглушить метод контроллера приложения, который устанавливает ivar (и был заглушен бесконечным wanking о том, почему вы не должны этого делать) здесь, способ, который работает, с ароматом Rspec около октября 2013 года.

before(:each) do
  campaign = Campaign.create!
  ApplicationController.any_instance.stub(:load_campaign_singleton)
  controller.instance_eval{@campaign = campaign}
  @campaign = campaign
end

он блокирует метод, чтобы ничего не делать, и устанавливает ivar на экземпляр контроллера rspec и делает его доступным для теста как @campaign.

Ответ 5

Ни один из предоставленных ответов не работал у меня. Как и в исходном посте @matt-fordam, у меня есть спецификация запроса, а не спецификация контроллера. Тест просто отображает представление без запуска контроллера.

Я решил это, наложив метод на представление, как описано в этом другом сообщении SO

view.stub(:current_user).and_return(etc)