【问题标题】:I need help to write the rspec test in rails我需要帮助才能在 rails 中编写 rspec 测试
【发布时间】:2023-05-21 14:52:01
【问题描述】:

我有一个 items_controller.rb

  def get_serialized_copy_of_item
    @item= Item.find_by_id(params[:id]) 
    if @item.nil?
      head :no_content
    else
      respond_to do |format|
      serialized_item = @item.as_json(include: [:test1, :test2, :test3, :test4])
      format.html
      format.json { render json: serialized_item }  
      end
    end
  end

routes.rb

namespace :items do
  get '/get_serialized_copy_of_item/:id', to:'items#get_serialized_copy_of_item'
end

我想写一个 rspec 测试

  1. 提交不正确的商品 ID 并确保返回 204

我已经完成了

require 'spec_helper'

describe Items::ItemsController do
  describe "GET items#get_serialized_copy_of_item" do
     it "renders 204 status code" do
      get "/items/get_serialized_copy_of_item/dfsdf"
      expect(last_response.status).to eq(204)
    end
  end
end

错误:我收到路由错误

F

Failures:

  1) Items::ItemsController GET items#item renders 204 status code
     Failure/Error: get "/items/get_serialized_copy_of_item/dfsdf"
     ActionController::RoutingError:
       No route matches {:controller=>"items/items", :action=>"/items/get_serialized_copy_of_item/dfsdf"}
     # ./spec/controllers/items/items_controller_spec.rb:6:in `block (3 levels) in <top (required)>'

Finished in 0.01576 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/controllers/items/items_controller_spec.rb:5 # Items::itemsController GET items#item renders 204 status code

捆绑 exec rake 路由

                                       GET    `items/get_serialized_copy_of_item/:id(.:format)                            items/items#get_serialized_copy_of_item`

谢谢

【问题讨论】:

  • 能否将bundle exec rake routes 的输出添加到问题的末尾?
  • @sixty4bit 添加。

标签: ruby-on-rails ruby ruby-on-rails-3 rspec


【解决方案1】:

RSpec 假定控制器名称来自测试名称。注意this doc中的例子:

describe WidgetsController do
  describe "GET index" do
    it "has a 200 status code" do
      get :index
      response.code.should eq("200")
    end
  end
end

这里RSpec由于describe WidgetsController已经知道了路径的widgets部分,所以get方法只需要:index作为参数。

将其转化为您的情况:

describe Items::ItemsController do
  describe "GET get_serialized_copy_of_item" do
     it "renders 204 status code" do
      get :get_serialized_copy_of_item, id: 'sdf'

      expect(response.status).to eq(204)
    end
  end
end
  1. 您只需将操作的名称传递给get() 方法,而不是整个路径。
  2. 您需要包含:id 参数作为get() 的第二个参数
  3. 似乎namespace 是在这里进行路由的错误方式。尝试将您的路线定义更改为:
resources :items do 
  member do 
    get :get_serialized_copy
  end
end

这将生成以下路线:

➜  bundle exec rake routes
   Prefix Verb   URI Pattern     

    Controller#Action
get_serialized_copy_item GET    /items/:id/get_serialized_copy(.:format) items#get_serialized_copy

为此,您希望在app/controllers/items_controller.rb 中拥有您的ItemsController

【讨论】:

  • 我试过了,但我得到了同样的错误。我也试过describe ItemsController
  • 这个答案对我来说是正确的。你还在得到这个:No route matches {:controller=&gt;"items/items", :action=&gt;"/items/get_serialized_copy_of_item/dfsdf"} 吗?
  • @JagdeepSingh,是的ActionController::RoutingError: No route matches {:id=&gt;"sdf", :controller=&gt;"items/items", :action=&gt;"get_serialized_copy_of_item"}
  • @kavin 这绝对不是以前的错误。注意问题仍然是:controller 部分:它说没有路由与控制器items/items 匹配。所以你的路由和/或命名空间有问题
  • @kavin 我在回答的末尾添加了更多关于如何修复路由的内容
【解决方案2】:

据我所知,没有任何嵌套。

如果是这样,您应该调用ItemsController 而不是Items::ItemsController

items_controller_spec:

require 'spec_helper'

describe ItemsController do
  describe "GET #get_serialized_copy_of_item" do
     it "renders 204 status code" do
      get "/items/get_serialized_copy_of_item/dfsdf"
      expect(last_response.status).to eq(204)
    end
  end
end

【讨论】:

    最近更新 更多