2014-05-06 51 views
0

我想爲完美工作的模型編寫一個測試 - 但由於某種原因測試沒有返回預期的結果。工廠是否會自動在模型中運行方法?

我的模型包含此:

after_validation :set_conference 

    def rand_conference 
    r = rand.to_s[2..8] 
    while conference == r 
     r = rand.to_s[2..8] 
    end 
    r 
    end 

    def set_conference 
    self.conference = rand_conference unless conference.presence 
    end 
end 

而在我的模型試驗我測試這個(理想情況下,我將測試如果「會議」是一個6位數字,但現在只是一個「不是零」就足夠了):

廠:

FactoryGirl.define do 
    factory :plan do 
    name "Test" 
    description "Lorem Ipsum" 
    category "template" 
    end 
end 

Model_spec:

before (:each) do 
    @plan = build(:plan) 
    end 


it "has a conference number" do 
    expect(@plan.conference).not_to be_empty 
end 

結果我得到:

1) Plan has a conference number 
    Failure/Error: expect(@plan.conference).not_to be_empty 
    NoMethodError: 
     undefined method `empty?' for nil:NilClass 

是否factorygirl使用after_validation回調?

回答

2

我想寫一個測試工作完美的模型 - 但由於某種原因測試沒有返回預期的結果。

測試沒有返回預期的結果,因爲after_validation回調永遠不會調用這就是爲什麼conference屬性nil。所以@plan.conference是零,你不能在nil對象上調用empty?。因此,錯誤undefined method 'empty?' for nil:NilClass

@plan = build(:plan)只想創建Plan模型的實例按在factory :plan指定的屬性,並將其分配給實例變量@plan它肯定不會運行任何驗證,顯然沒有ActiveRecord回調。

只要改變之前塊作爲

before (:each) do 
    @plan = create(:plan) ## create record in database 
end 

有了這個你after_validation回調將被觸發,你實際上是在數據庫中創建一個記錄。

參考:

回調是被調用在 對象的生命週期中的某些時刻的方法。通過回調,可以編寫代碼,只要活動記錄對象被創建,保存,更新, 刪除,驗證或從數據庫加載時, 將運行。

+0

問題解決了,這就實現了。加分結構非常好的解釋!更進一步,還有@fivedigit的答案,它也適用。 –

+0

很高興能幫到:) –

1

是的回調是自動運行。但是,您使用FactoryGirl.build來構建計劃,該計劃僅初始化對象但不驗證它。

您可能需要確保驗證的運行:

before (:each) do 
    @plan = build(:plan) 
end 

it "has a conference number" do 
    @plan.valid? 
    expect(@plan.conference).not_to be_empty 
end 

或者你需要調用FactoryGirl.create創建你的計劃,而且這也將在您的測試數據庫中創建它:

before (:each) do 
    @plan = create(:plan) 
end 

it "has a conference number" do 
    expect(@plan.conference).not_to be_empty 
end 
+0

謝謝!這也像一種魅力。你有沒有機會知道什麼是更快的方法 - 使用「創建」或「構建」+「有效?」 ? –

+0

儘量避免「創建」,因爲它們涉及I/O,因此它們使測試變得更慢。我寧願在測試驗證回調時觸發驗證。 – fivedigit

1

我認爲最abvious的辦法是明確的是這樣的:

it "has a conference number" do 
    @plan = build(:plan) 
    @plan.set_conference 
    expect(@plan.conference).not_to be_empty 
end 

無論如何,我不建議使用回調。我認爲最好使用service objects

+0

謝謝!我認爲其他解決方案在我的情況下效果更好,因爲他們使用我的驗證 - 但我肯定會看看服務對象! –

相關問題