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

Rails中如何用RSpec测试PostgreSQL类型的Enum字段?

在Rails中测试PostgreSQL原生Enum字段的问题

我有一个crops表,其中包含PostgreSQL原生类型的enum字段crop_type,对应的迁移代码、模型代码如下。使用RSpec的define_enum_for方法测试时出现错误,请问该如何测试这种非整数类型的Enum字段?

迁移代码

def up
  create_table :crops do |t|
    t.string :name
    execute <<-SQL
    CREATE TYPE crop_type AS ENUM ('fruit', 'vegetable', 'other_crop');
    SQL
    t.column :crop_type, :crop_type
    t.timestamps
  end
end

模型代码

class Crop < ApplicationRecord
  enum crop_type: { fruit: 'fruit', vegetable: 'vegetable', other_crop: 'other_crop' }
end

测试代码

it {
  should define_enum_for(:crop_type).with_values({ fruit: 'fruit', vegetable: 'vegetable', other_crop: 'other_crop' })
}

错误信息

Expected Crop to define :crop_type as an enum backed by an integer,
mapping ‹"fruit"› to ‹"fruit"›, ‹"vegetable"› to ‹"vegetable"›, and
‹"other_crop"› to ‹"other_crop"›. However, :crop_type is an enum column.


解决方案

RSpec的define_enum_for匹配器默认是为Rails内置的整数类型枚举设计的,而PostgreSQL原生Enum字段在Rails中直接映射为字符串值的枚举,因此会触发上述错误。你需要放弃使用define_enum_for,转而手动测试枚举的核心行为:

1. 验证枚举键值对的正确性

it 'defines correct crop_type enum mappings' do
  expect(Crop.crop_types).to eq(
    fruit: 'fruit',
    vegetable: 'vegetable',
    other_crop: 'other_crop'
  )
end

2. 测试实例的枚举方法

验证实例是否拥有枚举对应的赋值和查询方法:

describe '#crop_type enum methods' do
  let(:crop) { Crop.new }

  it 'supports setting via enum key methods' do
    crop.fruit!
    expect(crop.fruit?).to be true
    expect(crop.crop_type).to eq('fruit')
  end

  it 'supports direct value assignment' do
    crop.crop_type = 'vegetable'
    expect(crop.vegetable?).to be true
  end
end

3. 测试枚举查询作用域

验证基于枚举的类级查询方法是否正常工作:

describe 'crop_type scopes' do
  before do
    @fruit_crop = Crop.create!(name: 'Apple', crop_type: 'fruit')
    @vegetable_crop = Crop.create!(name: 'Carrot', crop_type: 'vegetable')
    @other_crop = Crop.create!(name: 'Mushroom', crop_type: 'other_crop')
  end

  it 'returns correct records for each scope' do
    expect(Crop.fruit).to include(@fruit_crop)
    expect(Crop.vegetable).to include(@vegetable_crop)
    expect(Crop.other_crop).to include(@other_crop)
  end
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:13:28