Почему rspe c не может найти мой маршрут без обязательных параметров? - PullRequest
2 голосов
/ 14 марта 2020

Фон

Я пытаюсь перенести старый ActionDispatch::IntegrationTest тест на rspe c.

Этот тест в настоящее время проходит:

require 'test_helper'

class HeartbeatControllerTest < ActionDispatch::IntegrationTest
  test "heartbeat" do
    get "/heartbeat"
    assert_response :success
  end
end

Контроллер

У меня есть HeartbeatController, который возвращает 200:

class HeartbeatController < ApplicationController
  def show
    render(json: { 'status': 'ok' })
  end
end

Он отлично работает с curl.

Маршрут

rake routes показывает маршрут:

                               Prefix Verb   URI Pattern                                                                              Controller#Action
                            heartbeat GET    /heartbeat(.:format)                                                                     heartbeat#show

Spe c

Мой тест довольно прост:

require 'rails_helper'

describe HeartbeatController do
  it 'succeeds' do
    get '/heartbeat'
    expect(response).to be_success
  end
end

Но когда я его запускаю

Failures:

  1) HeartbeatController succeeds
     Failure/Error: get '/heartbeat'

     ActionController::UrlGenerationError:
       No route matches {:action=>"/heartbeat", :controller=>"heartbeat"}
     # ./spec/controllers/heartbeat_controller_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.00718 seconds (files took 1.11 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/controllers/heartbeat_controller_spec.rb:4 # HeartbeatController succeeds

Вопросы

  • Почему этот тест не пройден?
  • Что я сделал не так?
  • Как можно отладить это, если переполнение стека не существует?

Ответы [ 2 ]

3 голосов
/ 14 марта 2020

Если это контроллер spe c, вы хотите передать имя метода, а не маршрут.

require 'rails_helper'

describe HeartbeatController do
  it 'succeeds' do
    get :show
    expect(response).to be_success
  end
end

Спецификации контроллера фактически не управляют всем стеком рельсов - они просто создают ложный запрос и передать его экземпляру контроллера и вызвать метод на контроллере.

Причина, по которой вы получаете ошибку маршрутизации, заключается в том, что ActionController::TestCase::Behavior пытается проверить, существует ли маршрут для данного заданного комбинированного имени контроллера / метода. Таким образом No route matches {:action=>"/heartbeat", :controller=>"heartbeat"}.

Весь этот процесс модульного тестирования контроллеров, как известно, имеет серьезные недостатки, поскольку вы макетируете огромные части платформы и фактически не тестируете, что делают контроллеры - они отвечают на запросы HTTP. Поскольку уровень маршрутизации и стек промежуточного программного обеспечения макетируются, ваши тесты не будут охватывать их, как настоящий тест интеграции.

Обе команды Rails и RSpe c препятствуют непосредственному тестированию контроллеров . Вместо этого используйте спецификации запроса , которые фактически управляют всем стеком.

# spec/requests/heartbeats_spec.rb
require 'rails_helper'

describe 'Heartbeats', type: :request do
  describe "GET /heartbeats" do
    it 'succeeds' do
      get '/heartbeat'
      expect(response).to be_successful
    end 
  end
end
0 голосов
/ 14 марта 2020

Вам необходимо указать действие контроллера в файле routes.rb.

Поскольку ваше действие контроллера show, вам, вероятно, понадобится что-то вроде

get ‘/heartbeat’ to: ‘heartbeat#show’

Подробнее здесь:

Rails Routing Docs

...