Ruby-on-rails 如何在请求规范中存根 ApplicationController 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7448974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:58:45  来源:igfitidea点击:

How to stub ApplicationController method in request spec

ruby-on-railsrubyrspeccapybara

提问by Matt Fordham

I am needing to stub the response of a current_usermethod in an Rspec/capybara request spec. The method is defined in ApplicationControllerand is using helper_method. The method should simply return a user id. Within the test, I'd like this method to return the same user id each time.

我需要current_user在 Rspec/capybara 请求规范中存根方法的响应。该方法在ApplicationControllerhelper_method 中定义并正在使用。该方法应该简单地返回一个用户 ID。在测试中,我希望此方法每次都返回相同的用户 ID。

Alternatively, I could fix my problem by setting session[:user_id]in the spec (which is what current_userreturns)... but that doesn't seem to work either.

或者,我可以通过session[:user_id]在规范中设置(这是current_user返回的内容)来解决我的问题……但这似乎也不起作用。

Are either of these possible?

这两种都有可能吗?

Edit:

编辑:

Here is what I've got (it is not working. It just runs the normal current_user method).

这是我得到的(它不起作用。它只是运行正常的 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

Also not working:

也不起作用:

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

回答by fess .

skalee seems to have provided the correct answer in the comment.

skalee 似乎在评论中提供了正确答案。

If the method you're trying to stub is an instance method (most likely) and not a class method then you need use:

如果您尝试存根的方法是实例方法(最有可能)而不是类方法,那么您需要使用:

ApplicationController.any_instance.stub(:current_user)

ApplicationController.any_instance.stub(:current_user)

回答by jefflunt

Here are a couple of examples of the basic form.

这里有几个基本形式的例子。

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

In your particular case, I believe the proper form would be:

在您的特定情况下,我相信正确的形式是:

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

Here's a full working example from a project I work on:

这是我从事的一个项目的完整工作示例:

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

To explain my full example, basically what this does is verify that, when an ActionController::InvalidAuthenticityTokenerror is raised anywhere in the app, that a flash message appears, and the user is redirected to the portals_controller#indexaction. You can use these forms to stub out and return specific values, test an instance of a given error being raised, etc. There are several .stub(:action_name).and_[do_something_interesting]()methods available to you.

为了解释我的完整示例,基本上它的作用是验证当ActionController::InvalidAuthenticityToken应用程序中的任何地方出现错误时,会出现一条 flash 消息,并且用户被重定向到该portals_controller#index操作。您可以使用这些表单来存根并返回特定值、测试正在引发的给定错误的实例等。有几种.stub(:action_name).and_[do_something_interesting]()方法可供您使用。



Update(after you added your code): per my comment, change your code so it reads:

更新(添加代码后):根据我的评论,更改您的代码,使其显示为:

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

回答by iHiD

This works for me and gives me a @current_uservariable to use in tests.

这对我@current_user有用,并为我提供了一个在测试中使用的变量。

I have a helper that looks like this:

我有一个看起来像这样的助手:

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

And then in my request specs, I call:

然后在我的请求规范中,我调用:

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

回答by Michael Johnston

For anyone else who happens to need to stub an application controller method that sets an ivar (and was stymied by endless wanking about why you shouldn't do that) here's a way that works, with the flavour of Rspec circa October 2013.

对于碰巧需要存根设置 ivar 的应用程序控制器方法的任何其他人(并且因无休止地想知道为什么不应该这样做而受阻),这是一种有效的方法,具有大约 2013 年 10 月的 Rspec 风味。

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

it stubs the method to do nothing, and sets the ivar on rspec's controller instance, and makes it available to the test as @campaign.

它存根方法不做任何事情,并在 rspec 的控制器实例上设置 ivar,并使其作为 @campaign 可用于测试。

回答by Sbbs

For Rspec 3+ the new api is:

对于 Rspec 3+,新的 api 是:

For a controller test, nice and short:

对于控制器测试,很好很简短:

allow(controller).to receive(:current_user).and_return(@user)

Or for all instances of ApplicationController:

或者对于 ApplicationController 的所有实例:

allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(@user)

回答by jwadsack

None of the provided responses worked for me. As in @matt-fordam's original post, I have a request spec, not a controller spec. The test just renders the view without launching a controller.

提供的回复都没有对我有用。在@matt-fordam 的原始帖子中,我有一个请求规范,而不是控制器规范。测试只呈现视图而不启动控制器。

I resolved this by stubbing the method on the view as described in this other SO post

我通过在其他 SO 帖子中描述的视图上存根方法解决了这个问题

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