简体   繁体   中英

RSpec stub not working for integration test

Inside a controllers test, I want to test that when logged in, the controller renders the request fine, else if not logged in, it redirects to the login_path.

The first test passes fine as expected, no user is logged in, so the request is redirected to the login_path. However I've tried a myriad of stub/stub_chain's but still can't get the test to fake a user being logged in and render the page okay.

I would appreciate some direction on getting this to work as expected.

The following classes and tests are the bare bones to keep the question terse.

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

This is not working because you are stubbing the method current_user on the ApplicationController class, and not an instance of that class.

I would suggest stubbing it (correctly) on an instance of that class, but your test appears to be an integration test rather than a controller test.

What I would do instead then is as Art Shayderov mentioned is to emulate the sign-in action for a user before attempting to visit a place that requires an authenticated user.

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.")

In my applications, I've moved this into a helper method for my tests. This is placed into a file at spec/support/authentication_helpers.rb and looks like this:

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

Then in my request specs, I simply call the method to sign in as that particular user:

sign_in_as(user)

Now if you want to sign in using a standard controller test, Devise already has helpers for this. I generally include these in the same file ( spec/support/authentication_helpers.rb ):

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

Then you can sign in using the helpers like this:

 before do
   sign_in(:user, user)
 end

 it "performs an action" do
   get :index
 end

I would look at http://ruby.railstutorial.org/chapters/sign-in-sign-out#sec:a_working_sign_in_method .

The author describes how to write a sign_in method and use it in your rspec tests.

It doesn't look like controller test. It looks more like rspec-rails request spec which simulates browser. So stabbing controller won't work, you have to either simulate sign in (something like this)

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

or manually add user_id to session.

If on the other hand you want to test controller in isolation your test should look like that:

get 'index'
response.should be_success

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM