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

Minitest测试助手模拟会话时遇路由错误求助

管理员权限控制测试中的路由错误解决方法

问题描述

实现仅管理员可创建文章的权限控制时,使用Minitest编写CategoriesController测试,调用自定义sign_in_as方法模拟管理员登录时,出现如下路由错误:

ActionController::UrlGenerationError: No route matches {:action=>"/login_categories", :controller=>"categories", :params=>{:email=>"fardeenmhs@hotmail.com", :password=>"fardeen"}}
 test/test_helper.rb:16:in `sign_in_as'

相关代码

CategoriesController测试代码

require 'test_helper'

class CategoriesControllerTest < ActionController::TestCase
  setup do
    @category = Category.create(name: "Sports")
    @admin_user = User.create(username: "fardeen", email: "fardeenmhs@hotmail.com",password: "fardeen", admin: true)
  end

  test "should get index" do
    get :index
    assert_response :success
    # assert_not_nil assigns(:categories)
  end

  test "should get new" do
    sign_in_as(@admin_user)
    get :new
    assert_response :success
  end

  test "should create category" do
    sign_in_as(@admin_user)
    assert_difference('Category.count',1) do
      post :create, category: { name:"Travel" }
    end

    assert_redirected_to category_path(Category.last)
  end


  test "should not create category if not admin" do
    assert_no_difference('Category.count') do
      post :create, category: { name:"Travel" }
    end
    assert_redirected_to categories_path
  end

  test "should show category" do
    get :show, id: @category
    assert_response :success
  end

  test "should get edit" do
    sign_in_as(@admin_user)
    get :edit, id: @category
    assert_response :success
  end
end

sign_in_as助手方法代码

ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'

class ActiveSupport::TestCase
  ActiveRecord::Migration.check_pending!

  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  #
  # Note: You'll currently still have to declare fixtures explicitly in integration tests
  # -- they do not yet inherit this setting
  fixtures :all

  # Add more helper methods to be used by all tests here...
  def sign_in_as(user)
    post login_path, params: {email: user.email, password: "fardeen"} 
  end
end

路由信息

Prefix Verb   URI Pattern                    Controller#Action
            root GET    /                              pages#Welcome
           about GET    /about(.:format)               pages#about
        articles GET    /articles(.:format)            articles#index
                 POST   /articles(.:format)            articles#create
     new_article GET    /articles/new(.:format)        articles#new
    edit_article GET    /articles/:id/edit(.:format)   articles#edit
         article GET    /articles/:id(.:format)        articles#show
                 PATCH  /articles/:id(.:format)        articles#update
                 PUT    /articles/:id(.:format)        articles#update
                 DELETE /articles/:id(.:format)        articles#destroy
          signup GET    /signup(.:format)              users#new
           users GET    /users(.:format)               users#index
                 POST   /users(.:format)               users#create
       edit_user GET    /users/:id/edit(.:format)      users#edit
            user GET    /users/:id(.:format)           users#show
                 PATCH  /users/:id(.:format)           users#update
                 PUT    /users/:id(.:format)           users#update
                 DELETE /users/:id(.:format)           users#destroy
      categories GET    /categories(.:format)          categories#index
                 POST   /categories(.:format)          categories#create
    new_category GET    /categories/new(.:format)      categories#new
   edit_category GET    /categories/:id/edit(.:format) categories#edit
        category GET    /categories/:id(.:format)      categories#show
                 PATCH  /categories/:id(.:format)      categories#update
                 PUT    /categories/:id(.:format)      categories#update
           login GET    /login(.:format)               session#new
                 POST   /login(.:format)               session#create
          logout GET    /logout(.:format)              session#destroy
controller_login POST   /controller/login(.:format)    session#create

问题原因与修复方案

原因分析

CategoriesControllerTest继承自ActionController::TestCase,而sign_in_as方法中使用的login_path会被当前测试的控制器(categories)作用域影响,错误生成了/login_categories这个不存在的路由。

修复方案

有两种可靠的修复方式:

  1. 直接使用登录路由的字符串路径
    修改sign_in_as方法,绕过路由辅助方法的作用域问题:

    def sign_in_as(user)
      post '/login', params: { email: user.email, password: "fardeen" }
    end
    
  2. 直接设置会话模拟登录(推荐)
    控制器测试中无需走实际登录请求,直接在会话中设置用户ID即可,效率更高且无路由问题:

    def sign_in_as(user)
      session[:user_id] = user.id
    end
    
  3. 可选:指定路由的控制器消除作用域
    如果坚持使用路由辅助方法,可明确指定控制器:

    def sign_in_as(user)
      post login_path(controller: 'session'), params: { email: user.email, password: "fardeen" }
    end
    

另外,建议使用fixtures管理测试数据,或确保测试后数据被清理,避免测试间的状态干扰。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 05:14:58