2016-05-31 69 views
0
一個實例

考慮兩個模型:FactoryGirl如何創建一個由關聯創建回調

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,當我使用FactoryGirl.create(:book)。它將創建一個Book的實例,然後嘗試創建定義的關聯user。創建用戶後,after_create是觸發器,book2是爲user創建的。然後它試圖綁定book1user,並被唯一性關聯阻止。

現在我正在使用book = FactoryGirl.create(:user).book。這是最好的/正確的方式來做到這一點?我認爲它是如此直觀的說明,因爲我正在測試Book,我認爲這將是最好的book = FactoryGirl.create(:book)

非常感謝。

回答

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 

理想情況下,你可以處理createnot create一本書採用trait爲用戶,它會更容易模擬的場景!

+0

好主意。但是我得到了'(NoMethodError)'的未定義方法'和_return''嘗試你的示例,我不知道爲什麼。但是我用'after(:build){| user | user.class.skip_callback(:create,:after,:create_book_for_user)}' – larryzhao

+0

是否包含'include RSpec :: Mocks :: ExampleMethods' in rails_helper.rb –

+0

是的,對不起,我一開始就錯過了。我只是試着在''rails_helper.rb'中包含'include RSpec :: Mocks :: ExmpleMethods'。我仍然得到'NoMethodError:未定義的方法'allow'for#' – larryzhao