【发布时间】:2019-01-14 17:15:26
【问题描述】:
在为我的 Rails 应用程序运行 rspec(使用 Factory Bot)测试时,我遇到了一个(令人沮丧的!)错误。我看到以下错误:
ActiveRecord::NotNullViolation:
Mysql2::Error: Field 'group_id' doesn't have a default value: INSERT INTO `groups_users` VALUES ()
它是间歇性的 - 不同的测试会在不同的运行中抛出错误 - 这可能表明存在竞争条件?
我的模型配置为:
User habtm Groups
Groups habtm Users
员工必须属于一个组 - 验证:
validates :groups, presence: { message: 'Staff must be in at least one group' }, if: :staff?
用户
factory :a_staff_member, class: User do
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
username { "#{first_name}_#{last_name}".downcase.gsub(/[^a-z]/i, '') }
email { "#{first_name}.#{last_name}@example.ac.uk".downcase }
user_type { :staff }
groups {|s| [s.association(:group)]}
end
群组
FactoryBot.define do
factory :group do
sequence(:title) { |n| "Group Number #{n}" }
sequence(:short_title) { |n| "GRP#{n}" }
sequence(:url_slug) { |n| "grp#{n}" }
end
end
所有失败测试的共同因素是用户创建工厂(并且给定用户的组创建必须属于一个组) - 所以这是我一直集中精力的地方。
鉴于错误出现在 groups_users 表上,我猜它试图在组表中存在组之前将条目保存到连接表?
根据其他SO帖子和互联网拖网,我尝试了各种设置组的方法:
1) groups {|s| [s.association(:group)]}
2) after(:build) {|user| user.groups = [create(:group)]}
3) groups {[FactoryBot.create(:group)]}
用户只是通过实例化
let!(:staff_user) { FactoryBot.create(:a_staff_member) }
在个别规格中 - 所以没有什么令人兴奋的。
但是,无论我如何在工厂中创建小组,它都没有任何区别 - 而且我的想法已经用完了 - 任何指示或建议都将不胜感激!
【问题讨论】:
-
该验证不起作用,因为它是一个 catch-22。您必须先将用户记录插入数据库,然后才能将任何内容插入连接表,因为连接表需要用户 ID(并且记录在插入之前没有 ID)。您需要从一开始就重新考虑这一点。
-
感谢您的回复 - 我可能应该补充一下 - 这只是在测试中运行时出现的问题 - 代码本身有效(我可以通过 UI 成功创建用户 - 它也在测试中间歇性地工作套房)。没有循环依赖 - 只要组存在,用户就可以添加到其中。据我所知,这是我在工厂中创建组的方式以及持久化组的方式存在问题,因此可以通过 habtm 关系进行链接。
标签: ruby-on-rails factory-bot rspec-rails has-and-belongs-to-many ruby-on-rails-5.2