RSpec测试Rails嵌套路由报错:ActionController::RoutingError求助
嘿,作为Rails和测试领域的新手,遇到这种路由匹配问题太正常了,咱们一步步拆解解决~
先揪出你测试里的几个核心问题
- 误用了Capybara的
visit方法:visit是给系统/功能测试(模拟用户浏览器操作)用的,而你写的是控制器测试,应该用Rails内置的get/post这类直接调用控制器动作的方法,用visit肯定会报错。 - 路由辅助方法的参数传递有误:你的嵌套路由
client_source_recipes需要父级资源的参数,辅助方法的调用格式得搞对。 - 对
get方法的参数格式理解有偏差:控制器测试里的get方法用法和你尝试的有些不一样。
给你两种正确的测试写法
写法一:直接指定动作名(控制器测试首选,更清晰)
这种方式明确告诉测试你要调用recipes#index动作,把路由需要的所有参数放到params哈希里:
RSpec.describe RecipesController, :type => :controller do # 一定要确保每个测试前都执行登录! before(:each) { login_user } let(:client) { create :client } let(:source) { create :source, warehouse_id: 1, client_id: client.id } let(:valid_attributes) { { name: "name", source_id: source.id } } let(:valid_session) { {"warden.user.user.key" => session["warden.user.user.key"]} } describe "GET #index" do it "assigns all recipes as @recipes" do recipe = Recipe.create! valid_attributes # 正确的get调用方式 get :index, params: { client_id: client.id, source_id: source.id, locale: 'cs' }, session: valid_session expect(assigns(:recipes)).to eq([recipe]) end end end
写法二:使用路由辅助方法
如果你想用路由辅助方法client_source_recipes_path,要注意它需要接收父级资源(client和source,或者它们的ID),额外参数比如locale可以作为哈希传递:
# 用对象传递参数 get client_source_recipes_path(client, source, locale: 'cs'), session: valid_session # 或者用ID传递参数 get client_source_recipes_path(client.id, source.id, locale: 'cs'), session: valid_session
额外排查点(新手容易踩的坑)
- 确认登录逻辑生效:你的
valid_session依赖登录后的session数据,一定要用before(:each) { login_user }确保每个测试前都完成登录,不然session为空可能导致奇怪的路由报错。 - 验证资源关联正确性:可以加个小断言确认
source确实属于client:expect(source.client).to eq(client) - 确认路由定义正确:在终端运行
rails routes | grep client_source_recipes,检查输出和你给出的路由配置完全一致。
为什么你之前的写法会报错?
- 用
visit的写法:控制器测试上下文里没有visit方法(这是Capybara专属),强行调用肯定会触发路由/方法不存在的错误。 get client_source_recipes_path, params: { ... }:这种写法矛盾了——如果第一个参数是路由辅助方法生成的URL,就不需要再单独传params哈希,参数应该直接传给路由辅助方法。
内容的提问来源于stack exchange,提问作者ARK
相关产品推荐
相关产品推荐

