RSpec存根不适用于集成测试

时间:2012-06-09 20:45:07

标签: ruby-on-rails ruby testing rspec factory-bot

在控制器测试中,我想测试一下,登录后,控制器会将请求呈现为罚款,否则如果没有登录,则会重定向到login_path。

第一个测试按预期正常传递,没有用户登录,因此请求被重定向到login_path。但是我尝试过无数的stub / stub_chain但仍然无法通过测试来伪造用户登录并使页面正常呈现。

我希望能够按预期方式开展工作。

以下类和测试是保持问题简洁的基础。

的ApplicationController

class ApplicationController < ActionController::Base
include SessionsHelper

  private
  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
  helper_method :current_user
end

SessionsHelper

 module SessionsHelper

  def logged_in?
    redirect_to login_path, :notice => "Please log in before continuing..." unless current_user
   end
end

AppsController

class AppsController < ApplicationController

  before_filter :logged_in?

  def index
    @title = "apps"
  end
end

apps_controller_spec.rb

require 'spec_helper'
describe AppsController do

  before do
    @user = FactoryGirl.create(:user)
  end

  describe "Visit apps_path" do
    it "should redirect to login path if not logged in" do
      visit apps_path
      current_path.should eq(login_path)
    end

    it "should get okay if logged in" do
      #stubs here, I've tried many variations but can't get any to work
      #stubbing the controller/ApplicationController/helper
      ApplicationController.stub(:current_user).and_return(@user)
      visit apps_path
      current_path.should eq(apps_path)
    end
  end
end

3 个答案:

答案 0 :(得分:1)

这不起作用,因为你在current_user类上存在方法ApplicationController,而不是该类的实例。

建议在该类的实例上(正确地)对其进行存根,但是您的测试似乎是集成测试而不是控制器测试。

我要做的就是提及Art Shayderov,就是在尝试访问需要经过身份验证的用户的地方之前模拟用户的登录操作。

visit sign_in_path
fill_in "Username", :with => "some_guy"
fill_in "Password", :with => "password"
click_button "Sign in"
page.should have_content("You have signed in successfully.")

在我的应用程序中,我已将其转换为测试的辅助方法。它放在spec/support/authentication_helpers.rb的文件中,如下所示:

module AuthenticationHelpers
  def sign_in_as!(user)
    visit sign_in_path
    fill_in "Username", :with => user.username
    fill_in "Password", :with => "password"
    click_button "Sign in"
    page.should have_content("You have signed in successfully.")
  end
end

RSpec.configure do |c|
  c.include AuthenticationHelpers, :type => :request
end

然后在我的请求规范中,我只是调用该方法以特定用户身份登录:

sign_in_as(user)

现在,如果您想使用标准控制器测试登录,Devise已经为此提供了帮助。我通常将这些包含在同一个文件中(spec/support/authentication_helpers.rb):

 RSpec.configure do |c|
   c.include Devise::TestHelpers, :type => :controller
 end

然后你可以使用这样的助手登录:

 before do
   sign_in(:user, user)
 end

 it "performs an action" do
   get :index
 end

答案 1 :(得分:0)

我会看http://ruby.railstutorial.org/chapters/sign-in-sign-out#sec:a_working_sign_in_method

作者描述了如何编写sign_in方法并在rspec测试中使用它。

答案 2 :(得分:0)

它看起来不像控制器测试。它看起来更像是模拟浏览器的rspec-rails请求规范。所以刺伤控制器不起作用,你必须模拟登录(类似这样)

visit sign_in
fill_in 'username', :with => 'username'
...

或手动将user_id添加到会话。

另一方面,如果你想要独立测试控制器,你的测试应该是这样的:

get 'index'
response.should be_success