You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rspec请求测试遇ActionController::RoutingError:用户更新测试卡壳求助

嘿,我来帮你排查这个ActionController::RoutingError的问题~从你给出的代码来看,主要是测试类型混用和参数结构错误这两个点导致的,咱们一步步来解决:

1. 别同时混用控制器测试和请求测试类型

你在describe里写了type: [:request, :controller],但这两种测试的写法逻辑完全不一样:

  • 控制器测试(type: :controller)是直接调用控制器的动作方法(比如patch :update),不需要设置host,也不用完整URL;
  • 请求测试(type: :request)是模拟真实HTTP请求,需要用完整的路径(比如patch "/users/1"),这时候才需要设置host。

混用这两种类型会让Rspec不知道该用哪种测试模式解析你的请求,直接触发路由错误。所以你得二选一:要么写控制器测试,要么写请求测试。

2. 修正参数结构的嵌套问题

你的代码里参数套了两层params:

form_params = { params: { id: 1, email: "hello@example", name: "hello" } }
patch :update, params: form_params

这会导致实际传给控制器的参数变成params: { params: { id: 1, ... } },Rails找不到正确的:id参数来匹配路由,自然报错。另外,Rails的strong parameters通常要求用户属性嵌套在user键下(不然控制器会过滤掉这些参数),所以参数结构也要调整。

给你两个修正后的示例

控制器测试写法(推荐如果只是测控制器逻辑)

require 'spec_helper'

describe UsersController, type: :controller do
  # 先创建一个测试用的用户,避免用硬编码的id=1(可能数据库里不存在)
  let(:test_user) { User.create(email: "original@test.com", name: "Original Name") }

  describe "#update" do
    it "doesn't update user with invalid params" do
      # 直接传正确的参数结构:id + 嵌套在user键下的属性
      patch :update, params: { 
        id: test_user.id,
        user: { email: "hello@example", name: "hello" }
      }

      # 重新加载用户数据,断言属性没被修改
      test_user.reload
      expect(test_user.email).not_to eq("hello@example")
      expect(test_user.name).not_to eq("hello")
    end
  end
end

请求测试写法(如果要测完整HTTP流程)

require 'spec_helper'

describe "User Update Endpoint", type: :request do
  before(:each) { host! 'localhost:3000' } # 去掉末尾的斜杠,避免路径拼接出问题
  let(:test_user) { User.create(email: "original@test.com", name: "Original Name") }

  it "doesn't update user with invalid params" do
    # 请求测试要用完整的API路径
    patch "/users/#{test_user.id}", params: {
      user: { email: "hello@example", name: "hello" }
    }

    test_user.reload
    expect(test_user.email).not_to eq("hello@example")
    # 还可以断言响应状态码,比如expect(response).to have_http_status(:unprocessable_entity)
  end
end

最后再检查两个点

  • 确认你的config/routes.rb里有resources :users,这样Rails才会生成PATCH /users/:id的路由;
  • 检查UsersController的update动作是否正确设置了strong parameters,比如:
    def user_params
      params.require(:user).permit(:email, :name)
    end
    

这样调整后,路由错误应该就能解决啦~

内容的提问来源于stack exchange,提问作者Maayan Naveh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:35:51