我有两个ActiveRecord模型用户和帖子。这是我的用户模型。
class User < ActiveRecord::Base
has_many :posts
end
这是我的Post模型。
class Post < ActiveRecord::Base
belongs_to :user
after_initialize :set_name
private
def set_name
self.name = "Post #{self.user.posts.count + 1}"
end
end
这一切都很好,但是当我写工厂时
FactoryGirl.define do
factory :post do
content 'blah blah'
user
end
factory :user do
name 'Dummy name'
end
end
这是我的post_spec.rb文件
require 'rails_helper'
RSpec.describe Post do
context 'with valid values' do
it 'should be valid' do
expect(build(:post)).to be_valid
end
end
end
我的测试用例说不清楚
set_name
中nil类的未定义方法帖子
我不知道我哪里出错了。
答案 0 :(得分:0)
patkoperwas是正确的,您正在尝试在拥有关联的User对象之前初始化Post,您的after_initialize需求首先存在。如果必须使用after_initialize,则可以在创建Post之前创建一个创建User的工厂,然后使用该工具进行构建。
FactoryGirl.define do
factory :user do
name "blah blah"
factory :user_with_posts do
transient do
post_count = 1
end
after(:create) do |user, evaluator|
evaluator.post_count.times do
create :post, user: user
end
end
end
end
end
我不相信FactoryGirl中内置了(:build)功能。因此,在构建Post对象之前,您无法真正使用回调来创建用户。我要么创建一个user_with_post,要么显式创建一个用户,并在创建一个post对象时传入它。
RSpec.describe Post do
context 'with valid values' do
it 'should be valid' do
user = FactoryGirl.create :user_with_posts
post = user.posts.first
expect(post).to be_valid
end
end
答案 1 :(得分:-1)
您需要配置该关联https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations
FactoryGirl.define do
factory :user do
name 'Dummy name'
end
factory :post do
content 'blah blah'
association :user
end
end
如果您在没有用户的情况下使用工厂创建帖子,FactoryGirl将为您创建用户,如果您之前创建了用户并在创建帖子时传递了该用户,FactoryGirl将使用您提供的用户。
答案 2 :(得分:-1)
您可以像这样在Post工厂中使用with_initialize
:
factory :post do
content 'blah blah'
user
initialize_with { new(user: user) }
end
问题的原因在factory_bot文档中进行了描述:https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#custom-construction
为获得与ActiveRecord的最大兼容性,默认的初始化程序通过不带任何参数的构建类上调用new来构建所有实例。然后调用属性编写器方法来分配所有属性值。
这就是为什么Post工厂的after_initialize
钩中没有关联的用户。