为何我的控制器要求params哈希需重复嵌套?附代码示例
为关联recipient_id的ChallengeRequestsController编写RSpec测试
结合你给出的控制器逻辑,我来帮你梳理如何编写对应的RSpec测试,覆盖核心业务场景:
控制器代码回顾
class ChallengeRequestsController < ApplicationController def create @challenge_request = ChallengeRequest.new(challenge_params) recipient = User.find(params.require(:recipient_id)) # 方法其余部分已省略(比如关联recipient、保存等逻辑) end private def challenge_params params.require(:challenge_request).permit(:action) end end
RSpec测试代码
RSpec.describe ChallengeRequestsController, type: :controller do # 假设你用FactoryBot创建测试数据,不用的话可以替换成User.create(...) let(:current_user) { create(:user) } let(:existing_recipient) { create(:user) } # 如果控制器需要用户登录,这里用Devise测试helper处理登录逻辑 before do sign_in current_user end describe "#create" do context "传入有效的recipient_id和challenge参数" do it "成功创建ChallengeRequest并关联指定收件人" do # 模拟POST请求,传入所需参数 post :create, params: { recipient_id: existing_recipient.id, challenge_request: { action: "initiate_challenge" } } # 断言数据库新增了一条记录 expect(ChallengeRequest.count).to eq(1) # 验证创建记录的属性和关联关系 created_request = ChallengeRequest.first expect(created_request.action).to eq("initiate_challenge") # 根据实际关联方式调整,比如ChallengeRequest属于recipient的话: expect(created_request.recipient).to eq(existing_recipient) # 断言响应状态(比如重定向到列表或详情页) expect(response).to have_http_status(:redirect) end end context "传入不存在的recipient_id" do it "触发ActiveRecord::RecordNotFound异常" do expect { post :create, params: { recipient_id: 999999, # 不存在的用户ID challenge_request: { action: "initiate_challenge" } } }.to raise_error(ActiveRecord::RecordNotFound) end end context "缺失recipient_id参数" do it "返回错误响应" do post :create, params: { challenge_request: { action: "initiate_challenge" } } # 由于params.require(:recipient_id)会抛出ParameterMissing异常 # 可直接断言异常,或如果控制器有错误处理,断言对应响应状态 expect(response).to have_http_status(:bad_request) end end end end
关键测试点说明
- 前置复用:用
let定义可复用的测试用户,before块统一处理登录(如果需要认证),减少重复代码 - 有效场景验证:不仅断言数据库变化,还要验证业务核心逻辑——关联的收件人是否正确、属性是否符合传入参数
- 异常场景覆盖:覆盖收件人不存在、参数缺失的情况,确保控制器的错误处理符合预期
内容的提问来源于stack exchange,提问作者Brendan Jones
相关产品推荐
相关产品推荐

