RSpec测试中FactoryBot重复创建用户,求复用同一实例方案
问题描述
在Rails项目编写RSpec请求测试时,使用let定义的user1、user2、user3会在每个it块执行时重新创建实例,导致用户ID和邮箱每次都变化,希望所有测试用例复用同一批用户实例。
测试代码
RSpec.describe "Normal days ", type: :request do context 'User ' do before(:all) do DatabaseCleaner.strategy = DatabaseCleaner::NullStrategy end let(:user1) { create :user } let(:user2) { create :user } let(:user3) { create :user } it 'Check-In ' do check_in(user1) end it 'Check-Out ' do check_out end it 'get histories ' do get_histories end end end
环境信息
Gem列表
gem 'rspec' gem 'rspec-rails' gem 'factory_bot_rails', '5.2.0' gem 'faker', '~> 2.22' gem 'database_cleaner', '~> 1.5.3'
- Rails版本:~>5.2.1
- Ruby版本:2.6.5
实际结果
每个it块执行时,user1、user2、user3的ID和邮箱都会更新(如第一次check-in用例ID为1-3,第二次用例为4-6)。
期望结果
所有测试用例执行时,user1、user2、user3的ID和邮箱保持一致。
解决方案
1. 用before(:all)替代let创建用户
let的特性是懒加载且每个it块执行时都会重新求值,要复用实例,需在before(:all)中一次性创建用户,整个context下的所有it块会共用这些实例:
RSpec.describe "Normal days ", type: :request do context 'User ' do before(:all) do DatabaseCleaner.strategy = DatabaseCleaner::NullStrategy # 在before(:all)中创建用户,整个context共用 @user1 = create :user @user2 = create :user @user3 = create :user end # 测试结束后清理数据,避免干扰其他测试 after(:all) do DatabaseCleaner.clean_with(:truncation) # 恢复项目默认的清理策略(根据实际情况调整) DatabaseCleaner.strategy = :transaction end it 'Check-In ' do check_in(@user1) end it 'Check-Out ' do check_out end it 'get histories ' do get_histories end end end
2. 核心注意事项
before(:all)中需用实例变量(@user1)存储用户,不能继续用let,否则仍会在每个it块重新生成实例。- 必须在
after(:all)中手动清理数据:NullStrategy会禁用自动清理,若不清理,测试数据会残留到其他用例中。 - 测试结束后要恢复默认的DatabaseCleaner策略,避免影响后续测试的清理逻辑。
内容的提问来源于stack exchange,提问作者Sajid Ali
相关产品推荐
相关产品推荐

