路线在测试中不匹配,但在应用程序中被识别

时间:2018-07-02 09:13:57

标签: ruby-on-rails rspec ruby-on-rails-5

我正在遵循Michael Hartl's教程,第10章。尝试进行UsersControllerTest#test_should_redirect_edit_when_logged_in_as_wrong_user时,测试get edit_user_path(@user)失败。

get edit_user_path(@user)
ActionController::UrlGenerationError: No route matches {:action=>"/users/762146111/edit", :controller=>"users"}
from /Users/cello/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/actionpack-5.1.4/lib/action_dispatch/journey/formatter.rb:55:in `generate' 

但是:

Rails.application.routes.recognize_path '/users/762146111/edit', method: :get
=> {:controller=>"users", :action=>"edit", :id=>"762146111"}

下面是可能存在错误的代码( Rails 5.1.4 )。

routes.rb

Rails.application.routes.draw do
  root 'static_pages#home'

  get  '/help', to: 'static_pages#help'
  get  '/about', to: 'static_pages#about'
  get  '/contact', to: 'static_pages#contact'
  get  '/signup', to: 'users#new'
  post 'signup', to: 'users#create'
  get '/login', to: 'sessions#new'
  post '/login', to: 'sessions#create'
  delete '/logout', to: 'sessions#destroy'
  get 'sessions/new'

  resources :users
end

users_controller_test.rb

require 'test_helper'

class UsersControllerTest < ActionController::TestCase
  def setup
    @user       = users(:michael)
    @other_user = users(:archer)
  end

  test 'should redirect edit when logged in as wrong user' do
    log_in_as(@other_user)
    get edit_user_path(@user)
    assert flash.empty?
    assert_redirected_to root_url
  end
end

users_controller.rb

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update]
  before_action :correct_user,   only: [:edit, :update]

  def edit
    @user = User.find(params[:id])
  end

  private

  def logged_in_user
    unless logged_in?
      flash[:danger] = 'Please log in.'
      redirect_to login_url
    end
  end

  def correct_user
    @user = User.find(params[:id])
    redirect_to(root_url) unless current_user?(@user)
  end
end

2 个答案:

答案 0 :(得分:1)

本教程定义了集成测试(继承自ActionDispatch::IntegrationTest),而您上面的代码定义了 Controller Test (继承自{{1} }。

ActionController::TestCase是控制器测试的正确语法,因为它绕过URL识别并直接指定get :edit, ...。这令人困惑,并且是现在不鼓励使用控制器测试而推荐使用集成测试的几个原因之一,而这可能正是您要创建的。

为此,请更改:

:action

收件人:

class UsersControllerTest < ActionController::TestCase

(请注意,本教程在将class UsersControllerTest < ActionDispatch::IntegrationTest 放入ActionDispatch::IntegrationTest的测试中都使用tests/integration/作为基类,这有些令人困惑。 )

答案 1 :(得分:0)

您不能在规范中将直接url与'get'方法一起使用。

以您的规格而不是

get edit_user_path(@user)

使用

get :edit, params: { id: @user.id }

相同
patch user_path(@user)

改为使用patch :update