Rails控制器测试:如何验证指定服务类被正确调用且传入参数正确?
测试实现方案
以下是基于Rails生态常用的RSpec框架的测试代码,核心逻辑是对EsignGenieSendByTemplate的初始化方法做参数断言,同时mock服务的process方法避免触发真实第三方请求:
require "rails_helper" # 替换为你实际的控制器类名 RSpec.describe SignaturesController, type: :controller do # 提前准备测试依赖数据 let(:test_client) { Client.create!(name: "测试客户", 补充你的Client模型所有必填字段) } let(:test_external_docs) do [ ExternalDocument.create!(name: "合同1", 补充ExternalDocument模型必填字段), ExternalDocument.create!(name: "附件1", 补充ExternalDocument模型必填字段) ] end let(:test_form_values) { { signer_name: "张三", expire_date: "2024-12-31" } } describe "POST #send_for_signature" do it "使用正确参数初始化EsignGenieSendByTemplate服务" do # 配置服务初始化的参数断言 expect(EsignGenieSendByTemplate).to receive(:new).with( client: test_client, external_documents: test_external_docs, form_values: test_form_values.with_indifferent_access ).and_return(double(process: { "result" => "success" })) # 发起控制器请求 post :send_for_signature, params: { client_id: test_client.id, document_ids: test_external_docs.map(&:id), form_values: test_form_values } # 验证响应符合预期 expect(response).to have_http_status(:ok) end # 可选补充服务调用失败的场景测试 it "服务返回失败时响应对应错误信息" do error_desc = "签名方手机号缺失" allow(EsignGenieSendByTemplate).to receive(:new).and_return( double(process: { "result" => "fail", "error_description" => error_desc }) ) post :send_for_signature, params: { client_id: test_client.id, document_ids: test_external_docs.map(&:id), form_values: test_form_values } expect(response).to have_http_status(:unprocessable_entity) expect(JSON.parse(response.body)).to eq(error_desc) end end end
注意事项
- 如果使用Rails自带的Minitest框架,逻辑完全一致,只需要把RSpec的接收断言替换为Minitest对应的mock断言即可
- 测试中
form_values参数后加with_indifferent_access是因为控制器拿到的params默认是支持符号/字符串键混用的HashWithIndifferentAccess类型,加上该匹配可以避免参数类型不匹配导致的断言误判
内容的提问来源于stack exchange,提问作者Jeremy Thomas
相关产品推荐
相关产品推荐

