嵌套API:ActionController :: UrlGenerationError - 没有路由匹配

时间:2015-09-23 22:14:53

标签: ruby-on-rails rspec

我想用RSpec测试我的API。

Api :: V1 :: EventsController存在且具有create方法。我使用simple_token_authentication和pundit来保证安全。

的routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      # users/
      resources :users, only: [:show, :update] do
        # users/:id/events/
        resources :events
      end
    end
  end
end

规格:

RSpec.describe Api::V1::EventsController, type: :controller do

  describe 'events#create' do
    before {
      @user = User.create(email: 'm@m.fr', password: '12345678', password_confirmation: '12345678')
      @user.reload
    }

    it 'should 401 if bad credentials' do
      # Given the user

      # When
      post "/api/v1/users/#{@user.id}/events", {},
      {
        'x-user-email' => 'toto',
        'x-user-token' => 'toto'
      }

      # Then
      expect_status 401
    end
  end
end

我得到了这个错误:

   Failure/Error: post "/api/v1/users/#{@user.id}/events", {},
   ActionController::UrlGenerationError:
     No route matches {:action=>"/api/v1/users/1/events", :controller=>"api/v1/events"}

编辑并回答: 我很困惑,当我想使用rspec请求时,我正在使用rspec控制器。 这是我的工作示例:

RSpec.describe Api::V1::EventsController, type: :controller do

  describe 'events#create' do
    before {
      @user = User.create(email: 'm@m.fr', password: '12345678', password_confirmation: '12345678')
      @user.reload
    }

    it 'should 401 if bad credentials' do
      # Given the user

      # When
      post "/api/v1/users/#{@user.id}/events", {}.to_json,
      {
        'Accept' => 'application/json',
        'Content-Type' => 'application/json',
        'x-user-email' => 'toto',
        'x-user-token' => 'toto'
      }

      # Then
      expect_status 401
    end
  end
end

2 个答案:

答案 0 :(得分:3)

控制器规范中的post方法采用第一个参数的操作名称,而不是路径,因此不是:

post "/api/v1/users/#{@user.id}/events", #...

尝试:

post :create, #...

控制器规格是单元测试。如果要测试整个堆栈,请使用feature spec而不是控制器规范。

答案 1 :(得分:3)

您不需要使用完整路径执行请求,因为您已经在测试Api :: V1 :: EventsController。

因此,使用特殊语法会更好:

post :create, nil, {
  'x-user-email' => 'toto',
  'x-user-token' => 'toto'
}

expect(response.response_code).to eq 401

如果您想测试路线,您应该在路线规格中进行测试:

# spec/routing/api_v1_events_routing_spec.rb
require "spec_helper"

RSpec.describe Api::V1::EventsController do
  describe "routing" do
    it "#create" do
      expect(post: "/api/v1/users/1/events").to \
        route_to(controller: "api/v1/events", action: "create", user_id: "1") 
    end
  end 
end