Маршрут не совпадает в тесте, но распознается в приложении - PullRequest
0 голосов
/ 02 июля 2018

Я следую учебнику Майкла Хартла , глава 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 голосов
/ 02 июля 2018

Учебное пособие определяет Интеграционный тест (наследует от ActionDispatch::IntegrationTest), тогда как в приведенном выше коде определяется Контроллерный тест (наследуется от ActionController::TestCase).

get :edit, ... - правильный синтаксис для теста контроллера, потому что он обходит распознавание URL и напрямую указывает :action. Это сбивает с толку, и это одна из нескольких причин, по которой тесты контроллеров сейчас не рекомендуются в пользу интеграционных тестов, что, вероятно, вы и хотите создать.

Для этого измените:

class UsersControllerTest < ActionController::TestCase

до:

class UsersControllerTest < ActionDispatch::IntegrationTest

(Обратите внимание, что учебник, несколько сбивающий с толку, использует ActionDispatch::IntegrationTest в качестве базового класса и для тестов, в которые он вставляет tests/integration/ , и для тех, которые он вводит в tests/controllers/.)

0 голосов
/ 02 июля 2018

Вы не можете использовать прямой URL с методом 'get' в спецификации.

В вашей спецификации вместо

get edit_user_path(@user)

использование

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

то же самое с

patch user_path(@user)

используйте patch :update вместо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...