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

为何Controller测试中ActiveRecord为空,外部请求却正常?

Rails测试中数据库数据为空的问题

问题情况

编写了如下测试代码:

test "reward/balance with existing id returns 200" do
  get "/reward/balance?id=4"
  assert_response(200)
end

运行测试时,响应和测试外发起相同GET请求的结果完全不同:浏览器访问http://localhost:3000/reward/balance?id=4能得到预期响应,但测试中调用时ActiveRecord的User表为空。

对应的控制器处理方法:

def show
  if params[:id]
    if user = User.where(id: params[:id]).take
      render json: user["reward_balance"], status: :ok
      return
    else
      render json: {message: "#{User.all.inspect}"}, status: :bad_request
      return
    end
  else #If no id in params
    render json: {message: "Incorrect parameters"}, status: :bad_request
    return
  end     
end

添加调试代码后,测试返回"{\"message\":\"#\\u003cActiveRecord::Relation []\\u003e\"}",确认测试环境下User表无数据,但在Rails开发控制台调用User.all能看到存在的用户数据。

原因及解决方法

核心原因

Rails的测试环境和开发环境是完全隔离的:

  • 两者使用独立的数据库(开发库是development,测试库是test),开发环境的数据库数据不会自动同步到测试环境
  • Rails默认的测试框架会在每个测试运行前后自动清理数据库(比如通过事务回滚或截断表),保证每个测试都是在干净的环境中执行,避免测试间的相互干扰

解决办法

你需要在测试用例中预先创建需要的测试数据,常见的几种方式:

  1. 手动在测试中创建数据
    修改测试代码,先创建目标用户再发起请求:

    test "reward/balance with existing id returns 200" do
      # 先创建id为4的用户
      User.create!(id: 4, reward_balance: 50)
      get "/reward/balance?id=4"
      assert_response(200)
    end
    
  2. 使用Rails内置Fixtures
    在test/fixtures/users.yml中定义测试数据:

    test_user_4:
      id: 4
      reward_balance: 50
      # 补充其他必填字段
    

    然后在测试中调用fixture数据:

    test "reward/balance with existing id returns 200" do
      users(:test_user_4) # 加载fixture中的用户数据
      get "/reward/balance?id=4"
      assert_response(200)
    end
    
  3. 使用FactoryBot(推荐)
    安装FactoryBot gem后,定义用户工厂:

    # test/factories/users.rb
    FactoryBot.define do
      factory :user do
        id { 4 }
        reward_balance { 50 }
        # 补充其他必填字段
      end
    end
    

    然后在测试中生成数据:

    test "reward/balance with existing id returns 200" do
      create(:user) # 创建符合工厂定义的用户
      get "/reward/balance?id=4"
      assert_response(200)
    end
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:40:24