0

我正在关注Michael Hartl 的教程,第 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)。

路线.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
4

2 回答 2

1

本教程定义了一个集成测试(继承自ActionDispatch::IntegrationTest),而您上面的代码定义了一个控制器测试(继承自ActionController::TestCase)。

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

为此,请更改:

class UsersControllerTest < ActionController::TestCase

到:

class UsersControllerTest < ActionDispatch::IntegrationTest

(请注意,本教程有点令人困惑,它用作它放入的测试它放入ActionDispatch::IntegrationTest的测试的基类。)tests/integration/ tests/controllers/

于 2018-07-02T13:22:07.583 回答
0

您不能在规范中使用带有“get”方法的直接 url。

在您的规范中,而不是

get edit_user_path(@user)

采用

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

patch user_path(@user)

patch :update改为使用

于 2018-07-02T09:35:31.033 回答