【问题标题】:Rspec testing No Route Matches ActionController::UrlGenerationErrorRspec 测试没有路由匹配 ActionController::UrlGenerationError
【发布时间】:2017-07-07 00:58:34
【问题描述】:

我正在尝试对 Rspec 和 Controller 测试,更具体地说是 JSON 请求。在这种情况下,我正在尝试使用v1_devices_path 路线:

routes.rb

v1_device_scans POST   /v1/devices/:device_serial_number/scans(.:format) v1/scans#create
v1_device       GET    /v1/devices/:serial_number(.:format)              v1/devices#show
                PATCH  /v1/devices/:serial_number(.:format)              v1/devices#update
                PUT    /v1/devices/:serial_number(.:format)              v1/devices#update

还有我的控制器:

controllers/v1/devices_controller.rb

class V1::DevicesController < ApplicationController
  before_action :set_device, only: [:show, :update]
  respond_to :json

  def show
    @device = Device.find_by(serial_number: params[:serial_number])
    render :json => @device.as_json
  end

  def update
    if @device.update(device_params)
      render json: @device, status: :ok, location: @device
    else
      render json: @device.errors, status: :unprocessable_entity
    end
  end

  private

  def set_device
    @device = Device.find_by!(serial_number: params[:serial_number])
  end

  def device_params
    params.require(:device).permit(
      :serial_number,
      :name,
      :diagnostic_checkin_status,
      :diagnostic_dns,
      :diagnostic_ping,
      :assigned_internal_ip,
      :assigned_external_ip,
      :assigned_gateway_ip,
      :version,
      :timezone,
      :task_id,
      :scan_status,
      :scan_progress
    )
  end

end

到目前为止,我的测试非常简单......只是想确保我得到一些结果:

spec/controllers/v1/devices_controller_spec.rb

需要'rails_helper'

RSpec.describe V1::DevicesController, type: :controller do

  it "shows device info" do
    device = FactoryGirl.create(:device)
    get v1_device_path(device.serial_number), :format => :json
    expect(response.status).to be(200)
  end
end

经过一些调整,我的 url 看起来创建正确,但我仍然收到 no route matches 错误:

  1) V1::DevicesController shows device info
     Failure/Error: get v1_device_path(device.serial_number), :format => :json

     ActionController::UrlGenerationError:
       No route matches {:action=>"/v1/devices/41442305171c430ab253ba1ad95c5c61", :controller=>"v1/devices", :format=>:json}
     # /usr/local/bundle/gems/rails-controller-testing-1.0.2/lib/rails/controller/testing/template_assertions.rb:61:in `process'
     # /usr/local/bundle/gems/devise-4.3.0/lib/devise/test/controller_helpers.rb:33:in `block in process'
     # /usr/local/bundle/gems/devise-4.3.0/lib/devise/test/controller_helpers.rb:100:in `catch'
     # /usr/local/bundle/gems/devise-4.3.0/lib/devise/test/controller_helpers.rb:100:in `_catch_warden'
     # /usr/local/bundle/gems/devise-4.3.0/lib/devise/test/controller_helpers.rb:33:in `process'
     # /usr/local/bundle/gems/rails-controller-testing-1.0.2/lib/rails/controller/testing/integration.rb:12:in `block (2 levels) in <module:Integration>'
     # ./spec/controllers/v1/devices_controller_spec.rb:11:in `block (2 levels) in <top (required)>'

我做错了什么?

【问题讨论】:

  • 您可以尝试使用request 类型规范type: :request 吗?
  • 好吧,现在出现不同的错误:unknown keyword: format
  • 稍微调整一下,去掉format: :json。现在得到:Failure/Error: expect(response.status).to be(200) expected #&lt;Integer:401&gt; =&gt; 200 got #&lt;Integer:605&gt; =&gt; 302 Compared using equal?, which compares object identity, but expected and actual are not the same object. Use expect(actual).to eq(expected)`,如果你不关心这个例子中的对象身份。`
  • 您使用的是哪个 Rails 版本?
  • Rails 5. 顺便说一下,我是否也将 request 规范用于 PUT/PATCH?

标签: ruby-on-rails ruby rspec


【解决方案1】:

这是不将type 更改为request 的另一种解决方案。由于在show 设计路由中添加了serial_number 参数而显示此错误,您可以在get url 中添加serial_number

RSpec.describe V1::DevicesController, type: :controller do

  it "shows device info" do
    device = FactoryGirl.create(:device)
    get :show, params: { serial_number: device.serial_number }, :format => :json
    expect(response.status).to be(200)
  end
end

希望对你有所帮助。

【讨论】:

  • 这仍然产生No route matches {:action=&gt;"/v1/devices/0dea0ba7746c42d49c869ea7a9639144", :controller=&gt;"v1/devices", :format=&gt;:json}
  • 谢谢。我在我的项目中运行了这个也得到了同样的错误。你可以改成这个get :show, params: { serial_number: device.serial_number }, :format =&gt; :json
  • 是的,这行得通,我不必更改 type: :controller
【解决方案2】:

好的,从@sebastián 的评论开始,我将规范更改为:

require 'rails_helper'

RSpec.describe V1::DevicesController, type: :request do

  it "shows device info" do
    headers = {
      "ACCEPT" => "application/json",     # This is what Rails 4 accepts
    }

    device = FactoryGirl.create(:device)
    get v1_device_path(device.serial_number), :headers => headers
    expect(response.content_type).to eq("application/json")
  end
end

我的测试现在通过了。

【讨论】:

  • 你也可以使用get v1_device_path(device_serial_number, format: :json)
  • @RyanBigg 稍微改变了错误字符串,但仍然是no route matches..... No route matches {:action=&gt;"/v1/devices/ae04a224c8724a609dacb0567afd643f.json", :controller=&gt;"v1/devices"}
猜你喜欢
  • 2019-05-25
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
相关资源
最近更新 更多