【问题标题】:Controller test for nested resources嵌套资源的控制器测试
【发布时间】:2017-04-27 14:29:15
【问题描述】:

无法解决为嵌套属性创建索引路由测试的问题。我一直在尝试我所有的想法,但没有任何效果

我有 Service 模型和 ServiceRoute 模型。

ServiceRoute 属于_to 服务

和

Service has_many ServiceRoutes.

这是我的控制器:

class ServiceRoutesController < ApplicationController

before_action :set_service_route, only: [:show, :update, :destroy]
before_action :set_service, only: :create


def create
  @service_route = @service.service_routes.build(service_route_params)

  if @service_route.save
    render json: @service_route, status: :created, location: @service_route
  else
    render json: @service_route.errors, status: :unprocessable_entity
  end
end


private

  def set_service_route
    @service_route = ServiceRoute.find(params[:id])
  end

  def set_service
   @service = Service.find(params[:service_id])
  end

  def service_route_params
    params.require(:service_route).permit(:routes_list, :service_id)
  end
end

我使用 build 方法创建 ServiceRoute

我的 routes.rb 文件:

resources :services do
  resources :service_routes
end

测试“应该创建服务路由”有错误:

ActionController::UrlGenerationError:没有路由匹配 {:action=>"index", :controller=>"service_routes"} 缺少必需的键:[:service_id]

test "should create service_route" do
 assert_difference('ServiceRoute.count') do
  post service_service_routes_url, params: { service_route: {routes_list: 
  @service_route.routes_list, service_id: @service_route.service_id } }, 
 as: :json
end

我应该如何重构这个测试以匹配路由:/services/:service_id/service_routes

【问题讨论】:

  • 尝试从:service_route 键中发送:service_id 参数。很容易忽略这样的事情。
  • test "should create service_route" do assert_difference('ServiceRoute.count') do post service_service_routes_url, params: { service_route: { routes_list: @service_route.routes_list}, service_id: @service_route.service_id }, as : :json 结束
  • 你的意思是这样吗?不幸的是不起作用:/
  • 当您明确发送 POST 时,测试试图达到 :index 操作很奇怪。强制post :create 而不是发送路由。
  • 您从 :service_route 键中发送 :service_id 参数的解决方案适用于 service_routes_url 但请注意我要检查 service_service_routes_url跨度>

标签: ruby-on-rails ruby for-loop testing ruby-on-rails-5


【解决方案1】:

测试嵌套路由可能会在测试应该放置的位置方面带来一些混乱。虽然嵌套可能会让您觉得孩子的测试应该写在父测试的内部,但实际上它们应该被隔离在自己的测试用例中。

Rspec 使用测试用例类名称推断正在测试的控制器。您也可以使用类方法.tests 来指示它。

ActionController::TestCase 会自动推断控制器 under test 来自测试类名。如果控制器不能 从测试类名称推断,您可以显式设置它 +测试+。

尽管您可能想将路径用作方法.post 的第一个参数,但TestCase 需要一个操作名称,例如:index、:create、:update 等。测试的正确语法应该是:

post :create, params: {
  service_id: @service_route.service_id,
  service_route: {
      routes_list: @service_route.routes_list 
    }
  }

这是TestCase.get 的文档片段。

  # Simulate a GET request with the given parameters.
  #
  # - +action+: The controller action to call.
  # - +params+: The hash with HTTP parameters that you want to pass. This may be +nil+.
  # - +body+: The request body with a string that is appropriately encoded
  #   (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
  # - +session+: A hash of parameters to store in the session. This may be +nil+.
  # - +flash+: A hash of parameters to store in the flash. This may be +nil+.
  #
  # You can also simulate POST, PATCH, PUT, DELETE, and HEAD requests with
  # +post+, +patch+, +put+, +delete+, and +head+.
  # Example sending parameters, session and setting a flash message:
  #
  #   get :show,
  #     params: { id: 7 },
  #     session: { user_id: 1 },
  #     flash: { notice: 'This is flash message' }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多