我需要在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
答案 0 :(得分:57)
如果您尝试存根的方法是实例方法(最有可能)而不是类方法,那么您需要使用:
ApplicationController.any_instance.stub(:current_user)
答案 1 :(得分:14)
以下是基本表格的几个例子。
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
答案 2 :(得分: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}
答案 3 :(得分:2)
对于其他任何碰巧需要存根设置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的测试。
答案 4 :(得分:1)
所提供的回复都不适合我。和@ matt-fordam的原始帖子一样,我有一个请求规范,而不是控制器规范。该测试只是在不启动控制器的情况下渲染视图。
我通过在other SO post
中描述的视图上的方法来解决这个问题view.stub(:current_user).and_return(etc)
答案 5 :(得分:1)
对于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)