在管理员授权命名空间中逐一测试各接口授权是否冗余?
答案是:不需要逐一为每个接口的每个操作重复编写授权测试,更高效的做法是做分层测试,既保证认证逻辑的覆盖,又避免冗余。
1. 先单独测试BaseController的认证逻辑
既然整个Admin命名空间的控制器都继承自Api::Admin::BaseController,且这个基类通过before_action :authenticate_admin统一做了JWT认证,那你应该先针对这个基类写测试,验证它的拦截逻辑是否生效:
RSpec.describe Api::Admin::BaseController, type: :controller do # 用测试控制器模拟继承关系 class TestAdminController < Api::Admin::BaseController def index head :ok end end before do routes.draw do get 'test_admin', to: 'test_admin#index' end end describe 'authenticate_admin before_action' do context 'when no auth header is present' do it 'returns unauthorized' do get :index expect(response).to have_http_status(:unauthorized) end end context 'when valid auth header is present' do it 'allows access' do get :index, headers: authenticated_header expect(response).to have_http_status(:ok) end end end end
这个测试一旦通过,就意味着所有继承自该基类的Admin控制器都会自动应用这个认证逻辑,从根源上保证了命名空间的权限控制。
2. 对业务接口做抽样验证,而非全量重复
你不需要给每个REST接口的每个动作(GET/POST/PUT/DELETE)都写一遍带token和不带token的场景,只需要选1-2个核心接口(比如restaurants的列表接口和创建接口)各写一次授权测试,确认基类的认证逻辑被正确继承即可。
比如你现在写的GET /admin/restaurants的测试就很好,但其他接口(比如POST /admin/restaurants、PUT /admin/restaurants/:id)就不需要再重复写未授权的场景了,把测试精力放在业务逻辑本身(比如创建餐厅的参数校验、权限细分等)上即可。
3. 特殊情况特殊处理
如果某个Admin接口有特殊的认证逻辑(比如通过skip_before_action :authenticate_admin跳过了认证,或者额外加了角色权限校验),那这个接口必须单独写授权测试,覆盖它的特殊逻辑。
总结
这种分层测试的方式,既保证了认证逻辑的覆盖性,又不会让测试代码变得冗余难维护——以后如果要修改JWT认证的逻辑,只需要修改基类的测试,而不用去改几十个接口的重复测试。
内容的提问来源于stack exchange,提问作者Carl Edwards

