考虑两种模式:
class User < ActiveRecord::Base
has_one :book
after_create :create_book
end
class Book < ActiveRecord::Base
belongs_to :user
validate_uniqueness :user_id
end
每个用户都可以拥有并且只能拥有一本书。然后我在我的规格中定义了两个工厂:
factory :user do
end
factory book do
user
end
接下来是问题,当我为Book
编写测试时,我想为book1
创建记录Book
(让我们称之为),当我使用{{ 1}}。它将创建FactoryGirl.create(:book)
的实例,然后尝试创建定义的Book
关联。创建用户后,系统会触发user
,并为after_create
创建book2
。然后它尝试将user
与book1
绑定,并被唯一性关联阻止。
现在我正在使用user
。这是最好的/正确的方法吗?我认为这很直观,因为我正在测试book = FactoryGirl.create(:user).book
,我认为最好有Book
非常感谢。
答案 0 :(得分:1)
我认为我们可以使用trait
。这是一个例子:
<强>工厂强>
factory :user do
# Your config here
# Use trait
trait :without_book do
after(:build) do |user|
allow(user).to receive(:create_book).and_return true
end
end
trait :with_book do
allow(user).to receive(:create_book).and_call_original
end
transient do
# Use this by default but don't use this line also works
# because we create book in the normal behavior
with_book
end
end
<强>规格强>
context 'test user without book' do
let(:user) { FactoryGirl.create(:user, :without_book)
it 'blah blah' do
end
end
context 'test user with book' do
let(:user) { FactoryGirl.create(:user, :with_book)
# Or simply use this, because :with_book is default
# let(:user) { FactoryGirl.create(:user)
it 'blah blah' do
end
end
顺便说一句,如你所见,我在allow(user).to receive(:create_book).and_return true
使用了一个存根方法,基本上,这个实用工具方法来自rspec-mock
,我们需要这个配置才能在工厂中使用它:
<强>规格/ rails_helper.rb 强>
FactoryGirl::SyntaxRunner.class_eval do
include RSpec::Mocks::ExampleMethods
end
理想情况下,您可以使用create
为用户处理一本书not create
或trait
,模拟场景会更容易!