[英]How to stub ApplicationController method in request spec
我需要在Rspec / capybara请求规范中存根current_user
方法的响应。 该方法在ApplicationController
定义,并使用helper_method。 该方法应该只返回一个用户ID。 在测试中,我希望这种方法每次都返回相同的用户ID。
或者,我可以通过在规范中设置session[:user_id]
来修复我的问题(这是current_user
返回的内容)......但是这似乎也不起作用。
这些都可能吗?
编辑:
这是我得到的(它不工作。它只运行正常的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
skalee似乎在评论中提供了正确的答案。
如果您尝试存根的方法是实例方法(最有可能)而不是类方法,那么您需要使用:
ApplicationController.any_instance.stub(:current_user)
以下是基本形式的几个例子。
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
错误时,出现flash消息,并且用户被重定向到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
这对我@current_user
并给我一个@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}
对于其他任何碰巧需要存根设置ivar的应用程序控制器方法的人(并且由于无法解释为什么你不应该这样做而受到阻碍)这里有一种方式可行,Rspec的味道大约在2013年10月。
before(:each) do
campaign = Campaign.create!
ApplicationController.any_instance.stub(:load_campaign_singleton)
controller.instance_eval{@campaign = campaign}
@campaign = campaign
end
它会使方法无效,并在rspec的控制器实例上设置ivar,并使其可用于@campaign的测试。
对于Rspec 3+,新api是:
对于控制器测试,好的和短的:
allow(controller).to receive(:current_user).and_return(@user)
或者对于ApplicationController的所有实例:
allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(@user)
所提供的回复都不适合我。 和@ matt-fordam的原始帖子一样,我有一个请求规范,而不是控制器规范。 该测试只是在不启动控制器的情况下呈现视图。
我通过在视图中对方法进行存根来解决这个问题,如其他SO帖子所述
view.stub(:current_user).and_return(etc)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.