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

RSpec测试Active Campaign报Invalid Record User Must exist错误

问题原因

测试失败由两个直接问题导致,附带一个隐藏的控制器代码bug:

  • 测试参数硬编码app_user_id: 12,但测试环境使用独立的事务性测试数据库,默认每次运行测试会清空数据。你定义的let(:user) { create(:user) }是懒加载逻辑,整个测试用例中从未引用过user变量,因此这个测试用户根本不会被创建;就算引用了,FactoryBot生成的第一条用户id为1,和你硬编码的12完全不匹配,Token模型校验关联用户存在性时找不到对应id的用户,自然返回user must exist的422错误。
  • 断言逻辑完全错误:你对响应体执行JSON.dump得到的是序列化后的字符串,直接和整数200做相等比对永远不可能通过,你需要比对的是HTTP响应状态码,或者解析响应体后校验业务返回字段。
  • 控制器存在隐藏变量名笔误:update_contact方法中先赋值contact = create_token,后续构造请求参数时却写了token.email_token,token是未定义的局部变量,触发到对应分支会直接抛NameError,非测试环境能跑通只是因为你没覆盖到这个执行路径。
修复方案
  1. 调整测试用例的用户定义和参数逻辑,不要硬编码用户id,确保测试用户提前创建:
    • 把let改成let!,强制在执行测试用例前就创建测试用户,避免懒加载不生效的问题
    • 参数中的app_user_id使用实际创建的测试用户id,不要写死12
  2. 修正断言逻辑,正确校验HTTP状态码和响应体内容
  3. 修正控制器里的变量名笔误,把token.email_token改成contact.email_token

修正后的测试代码:

require 'rails_helper'

RSpec.describe 'Create Token for Active Campaign', type: :request do
  # let! 强制提前创建记录,避免懒加载不执行
  let!(:user) { create(:user) }
  let(:create_active_params) do
    {
      contact: {
        id: '100',
        email: 'john@sample.com',
        app_user_id: user.id, # 关联实际创建的测试用户
        first_name: 'john',
        last_name: 'Doe',
        tags: 'form-step-1'
      }
    }
  end

  it 'updates a contact' do
    VCR.use_cassette('update_contact') do
      post '/api/v1/active_campaign_contacts', params: create_active_params.to_json, headers: { 'Content-Type' => 'application/json' }
      # 正确断言HTTP状态码
      expect(response).to have_http_status(:ok)
      # 解析响应体校验业务结果
      response_body = JSON.parse(response.body)
      expect(response_body['success']).to be true
    end
  end
end

需要同步修正的控制器代码片段:

def update_contact
  contact = create_token
  url = URI("#{BASE_URL}/api/3/contacts/#{contact.active_campaign_id}")
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true

  request = Net::HTTP::Put.new(url)
  request['Accept'] = 'application/json'
  request['Content-Type'] = 'application/json'
  request['api-token'] = API_KEY
  # 修正变量名,把token改成contact
  data = { contact: { fieldValues: [{ field: '1', value: contact.email_token }] } }
  request.body = JSON.dump(data)
  response = http.request(request)
  response.code == '200' ? render(json: { success: true }) : render(json: { success: false })
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:18:20