【问题标题】:RSpec error ActionController::UrlGenerationError: when testing controllerRSpec 错误 ActionController::UrlGenerationError: 测试控制器时
【发布时间】:2021-07-28 21:27:22
【问题描述】:

我正在为我的 API 控制器编写规范(使用 RSpec)。当我测试索引的 GET 请求时一切正常,它返回预期的正文和成功的响应,但是,当我测试 show 操作的 GET 请求时,它会引发以下错误:

ActionController::UrlGenerationError:
   No route matches {:action=>"show", :controller=>"api/v1/contacts"}

这是我在规范文件中编写的代码:

require 'rails_helper'

RSpec.describe Api::V1::ContactsController do
  describe "GET #index" do
    context 'with a successful request'  do
      before do
        get :index
      end

      it "returns http success" do
        expect(response).to have_http_status(:success)
        expect(response.status).to eq(200)
      end

      it "JSON body response contains expected recipe attributes" do
        json_response = JSON.parse(response.body)
        expect(json_response.keys).to match_array(%w[data included])
      end
    end
    end

  describe "GET #show" do
    context 'with a successful request'  do
      before do
        get :show
      end

      it "returns http success" do
        expect(response).to have_http_status(:success)
        expect(response.status).to eq(200)
      end
    end
  end
end

这是命令rails routes 打印的显示路由

谁能帮我看看我错过了什么? 如何使用 RSpec 测试 show 操作的 GET 请求?

【问题讨论】:

    标签: ruby-on-rails rspec


    【解决方案1】:

    错误是由于您没有传递路由所需的 slug 参数:

    get :show, slug: contact.slug
    

    但您首先在这里真正想要的是request spec,而不是控制器规范。请求规范将实际的 HTTP 请求发送到您的应用程序。控制器规范模拟了大部分框架并让错误继续前进——尤其是路由错误。

    Rails 和 RSpec 团队不鼓励使用控制器规范,不应在遗留代码之外使用。

    # spec/requests/api/v1/contacts_spec.rb
    require 'rails_helper'
    
    RSpec.describe 'API V1 Contacts', type: :request do
    
      # This can be DRY:ed into a shared context
      let(:json){ JSON.parse(response.body) }
      subject { response }
      
      # This example uses FactoryBot
      # https://github.com/thoughtbot/factory_bot
      let(:contact) { FactoryBot.create(:contact) }
    
      # but you could also use a fixture
      let(:contact){ contacts[:one] }
      
      # describe the actual API and not how its implemented
      describe "GET '/api/v1/contacts'" do
        before { get api_vi_contacts_path }
        it { is_expected.to be_successful }
        it "has the correct response attributes" do
          expect(json.keys).to match_array(%w[data included])
        end
      end
      
      describe "GET '/api/v1/contacts/:id'" do
        before { get api_vi_contact_path(contact) }
        it { is_expected.to be_successful }
        # @todo write examples about the JSON
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多