Rails Minitest中如何正确测试polymorphic多态关联记录
Rails Minitest 多态关联记录正确测试方案
问题复现
使用associable:references{polymorphic}生成多态关联后,数据库schema对应字段为:
t.string "associable_type", null: false t.bigint "associable_id", null: false
Rails自动生成的fixtures初始内容为:
associable: one associable_type: Associable
开发者尝试手动修改fixtures,直接写字段值匹配表结构:
associable_id: 4 associable_type: Chain
运行测试代码时出现校验失败:
test "valid " do contact = Contact.new(associable_id: 2, associable_type: 'User') puts contact.valid? puts contact.errors.inspect assert contact.valid? end
返回错误:
false #<ActiveModel::Errors [#<ActiveModel::Error attribute=associable, type=blank, options={:message=>:required}>]>
尝试参照自动生成的fixtures语法,改为传入关联名的写法,又抛出变量未定义错误:
contact = Contact.new(associable: two, associable_type: 'User') # 报错:NameError: undefined local variable or method 'two'
错误原因
- 多态关联的存在性校验是针对关联对象本身的,单独给
associable_id、associable_type两个数据库字段赋值,不会完成关联对象的绑定,校验逻辑会判定associable关联缺失,直接触发必填报错。 - fixtures里的条目别名(比如
one/two)只在fixtures文件解析阶段生效,不是测试运行时的全局变量,在测试代码里直接写别名会被Ruby识别为未定义的本地变量,抛出NameError。
正确写法
Fixtures 配置
不要手动拆分填写associable_id和associable_type,直接使用Rails原生的多态关联简写语法,格式为关联别名 (关联类名),Rails会自动填充两个字段的值:
# contacts.yml # 关联User模型下别名为:one的fixture记录 one: associable: one (User) # 关联Chain模型下别名为:main的fixture记录 two: associable: main (Chain)
不需要额外配置
associable_type字段,Rails会根据括号内的类名自动匹配填充。
测试用例编写
在测试代码中初始化多态关联记录时,先通过fixture提供的访问方法拿到实际关联的模型对象,再赋值给关联属性即可,不需要手动传id和type:
test "contact with polymorphic associable is valid" do # 取出users.yml中定义的别名为:one的User记录 test_user = users(:one) # 直接绑定关联对象 contact = Contact.new(associable: test_user) assert contact.valid? end
如果要验证fixtures本身生成的记录合法性,直接通过fixture访问方法取对象校验即可:
test "generated contact fixtures are valid" do assert contacts(:one).valid? assert contacts(:two).valid? end
内容的提问来源于stack exchange,提问作者Jerome
相关产品推荐
相关产品推荐

