重写new方法的Rails ActiveRecord模型,如何用FactoryGirl定制测试主题?
问题与解决方案
问题背景
我有一个重写了new方法的Rails ActiveRecord模型Document,该方法需接收参数才能实例化包含必填字段的对象。在用Shoulda Matchers的RSpec模型测试中,我需要验证关联关系,目前只能通过直接传参实例化模型作为测试主题,想改用FactoryGirl工厂生成带定制参数的测试主题。
相关信息
模型代码
class Document < ApplicationRecord has_many :folders, dependent: :destroy belongs_to :project belongs_to :author, class_name: 'User' end
当前测试代码
require 'spec_helper' describe Document do describe 'associations' do it { should have_many(:folders).dependent(:destroy) } it { should belong_to(:project) } it { should belong_to(:author).class_name('User') } end end
技术栈
- Ubuntu 22.04.2 LTS
- Rails 5.2.2
- RSpec 3.8.0
- Shoulda-matchers 3.1.3
- FactoryGirl 4.9.0
解决方案
1. 定义Document工厂
在spec/factories/documents.rb中创建工厂,利用initialize_with调用重写后的new方法,传入必填参数:
FactoryGirl.define do factory :document do project { create(:project) } author { create(:user) } # 补充其他必填字段 initialize_with { new(project: project, author: author) } end end
注意:需确保
project和user的工厂已存在,若没有需先创建对应工厂文件。
2. 修改RSpec测试使用工厂
更新测试代码,指定测试主题为工厂生成的实例:
require 'spec_helper' describe Document do subject { build(:document) } describe 'associations' do it { should have_many(:folders).dependent(:destroy) } it { should belong_to(:project) } it { should belong_to(:author).class_name('User') } end end
额外说明
- 若重写的
new方法需要更多定制参数,可在工厂中添加对应属性并传入initialize_with; - 使用
build而非create是因为关联测试无需持久化对象,能提高测试效率; - 如需临时调整属性,可通过
build(:document, author: create(:admin_user))传入定制参数。
内容的提问来源于stack exchange,提问作者Anas Shahid
相关产品推荐
相关产品推荐

