包含redirect_to的测试因rspec而失败,但应用程序正在按预期工作。 Michael Hartl的第9.6.6章(第4.0版)

时间:2013-09-14 07:45:30

标签: ruby-on-rails ruby rspec ruby-on-rails-4 railstutorial.org

我正在尝试解决Michael Hartl的第9.6章Rails v 4.0中的问题6。

虽然在rspec测试中一切都很好看:

  describe "should redirect a logged in user to root url if user tries to hit new in users controller" do
    let(:user) {FactoryGirl.create(:user)}
    before do
      sign_in user
      get new_user_path
    end

    specify{expect(response).to redirect_to(root_url)}
  end

  describe "should redirect a logged in user to root url if user tries to hit create in users controller" do
    let(:params) do {user: {name: "Tester", email: "test@example.com", password: "password",
                            password_confirmation: "password"}}
    end
    let(:user) {FactoryGirl.create(:user)}

    before do
      sign_in user
      post users_path, params
    end

    specify{expect(response).to redirect_to(root_url)}
  end

这是我的控制器片段:

class UsersController < ApplicationController
before_action :is_signed_in, only: [:new, :create]
def new
  @user = User.new
end

def create
  @user = User.new(user_params)
  if @user.save
    sign_in @user
    flash[:success] = "Welcome to the Sample App!"
    redirect_to @user
  else
    render 'new'
  end
end

 private
  def is_signed_in
    redirect_to(root_url) if signed_in?
  end
end
utilities.rb中的

sign_in方法

def sign_in(user, options = {})
  if options[:no_capybara]
    # Signin when not using capybara
    remember_token = User.new_remember_token
    cookies[:remember_token] = remember_token
    user.update_attribute(:remember_token, User.encrypt(remember_token))
  else
    visit signin_path
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Sign In"
  end
end

但我的测试用例失败并出现以下错误:

Failures:

  1) Authentication signin with valid information should redirect a logged in user to root url if user tries to hit create in users controller
   Failure/Error: specify{expect(response).to redirect_to(root_url)}
   Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/users/2>.
   Expected "http://www.example.com/" to be === "http://www.example.com/users/2".
 # ./spec/requests/authentication_pages_spec.rb:69:in `block (5 levels) in <top (required)>'

  2) Authentication signin with valid information should redirect a logged in user to root url if user tries to hit new in users controller
 Failure/Error: specify{expect(response).to redirect_to(root_url)}
   Expected response to be a <redirect>, but was <200>
 # ./spec/requests/authentication_pages_spec.rb:55:in `block (5 levels) in <top (required)>'

Finished in 5.22 seconds
95 examples, 2 failures

Failed examples:

rspec ./spec/requests/authentication_pages_spec.rb:69 # Authentication signin with valid information should redirect a logged in user to root url if user tries to hit create in users controller
rspec ./spec/requests/authentication_pages_spec.rb:55 # Authentication signin with valid information should redirect a logged in user to root url if user tries to hit new in users controller

Randomized with seed 58509

我尝试调试,但无法弄清楚确切的问题。任何人都可以帮我吗?

编辑:1:添加了route.rb 的routes.rb

    SampleApp::Application.routes.draw do
      resources :users
      resources :sessions, only: [:new, :create, :destroy]
      root "static_pages#home"
      match '/help', to: "static_pages#help", via: 'get'
      match '/about', to: "static_pages#about", via: 'get'
      match '/contact', to: "static_pages#contact", via: 'get'
      match '/signup', to: "users#new", via: 'get'
      match '/signin', to: "sessions#new", via: 'get'
      match '/signout', to: "sessions#destroy", via: 'delete'
   end

编辑2 我正在用水豚测试它。

的Gemfile

group :test do
  gem 'selenium-webdriver', '2.35.1'
  gem 'capybara', '2.1.0'
  gem 'growl', '1.0.3'
  gem 'factory_girl_rails', '4.2.1'
  gem 'database_cleaner', '<1.1.0'
  gem "launchy", "2.3.0"
  gem 'cucumber-rails', '1.4.0', :require => false
end

session_helper.rb

module SessionsHelper

  def sign_in(user)
    remember_token = User.new_remember_token
    cookies.permanent[:remember_token] = remember_token
    user.update_attribute(:remember_token, User.encrypt(remember_token))
    self.current_user = user
  end

  def current_user=(user)
    @current_user = user
  end

  def current_user
    remember_token = User.encrypt(cookies[:remember_token])
    @current_user ||= User.find_by(remember_token: remember_token)
  end

  def signed_in?
    !current_user.nil?
  end

  def sign_out
    self.current_user = nil
    cookies.delete(:remember_token)
  end

  def current_user?(user)
    current_user == user
  end

  def store_location
    session[:return_to] = request.url if request.get?
  end

  def redirect_back_or(default)
    redirect_to(session[:return_to] || default)
    session.delete(:return_to)
  end

  def signed_in_user
    unless signed_in?
      store_location
      redirect_to signin_url, notice: "Please sign in."
    end
  end
end

1 个答案:

答案 0 :(得分:1)

我相信你错过了这个:

no_capybara: true

所以看起来应该是这样的:

before do
  sign_in user, no_capybara: true
  get new_user_path
end

和此:

before do
  sign_in user, no_capybara: true
  post users_path, params
end

这是我与你的对比之间的唯一区别。希望它有效!