2016-09-23 54 views
0

我遇到以下代碼的問題,它只在某些時候運行它。Activerecord創建方法有時不能及時工作

require_relative 'spec_helper' 
require 'pry' 

RSpec.describe Round do 
    testFruit = [Fruit.create(name: "Anjou Pear", unit: "10/LB", price: 13.24), Fruit.create(name: "Anjou Bear", unit: "10/LB", price: 15.24)] 

    before(:each) do |variable| 
    @round = Round.new 
    end 

    it 'returns all fruit in the current round of ordering' do 
    expect(@round.fruits).to match_array(testFruit) 
    end 
    it 'lets you clear the list for the next round' do 
    @round.next 
    expect(@round.fruits).to match_array([]) 
    end 
end 

@round.fruits被定義爲

def fruits 
    Fruits.all 
end 

所以我理解Fruits.all必須等待testFruits要永久保存的資料庫,我猜這是不是在按時完成?有沒有一種方法可以用rspec異步測試,並且應該以不同的方式設計我的測試以避免此問題?

我得到的是 ``` 故障/錯誤的錯誤:預期(@ round.fruits)。爲了match_array(testFruit)

expected collection contained: [#<Fruit id: 53, pic: nil, description: nil, name: "Anjou Pear", unit: "10/LB", price: #<BigDecimal:2...l:206de28,'0.1524E2',18(27)>, created_at: "2016-09-27 18:18:23", updated_at: "2016-09-27 18:18:23">] 
    actual collection contained: [] 

```

+0

將testFruit = [...]前面的內容(:each)作爲@testFruit = [...]並且它應該可以工作,您不會在示例之外或之前創建對象(:each)該數據將保留在數據庫 – arieljuod

+0

因此,在運行規範之後,在before(:each)塊中創建的對象將被刪除/不會在數據庫中持久存在? –

+0

是的,在before(:each)塊內創建的對象將不會持續用於下一個spec。如果你之前創建了一個以外的(:each)(例如之前(:all)),你必須在你的規範之後(使用after(:all)塊)刪除它,或者使用數據庫清理寶石(比如DatabaseCleaner)或者你最後會有一個測試數據庫,裏面裝滿了舊版本的垃圾。 – arieljuod

回答

1

Is there a way I can test this asynchronously with rspec

是,但我不會在此討論這一點,因爲如果您以與當前最佳做法更一致的方式編寫測試,則沒有必要。

should I be designing my tests differently to avoid this issue?

是的,這裏的問題很可能是由於測試之間被稱爲「泄漏狀態」。理想的做法是每個測試都應該完全與每個測試分離開來,以便您可以按任意順序運行測試,並獲得相同的結果。

問題是你剛剛在範圍內的testFruit數組。如果此數組或其在數據庫中創建的對象發生更改,則該更改會泄露到之後的測試中。

我建議,而不是寫你的測試是這樣的:

RSpec.describe Round do 
    let!(:round) { Round.new } 
    let!(:test_fruit) do 
    [ 
     Fruit.create(name: "Anjou Pear", unit: "10/LB", price: 13.24), 
     Fruit.create(name: "Anjou Bear", unit: "10/LB", price: 15.24) 
    ] 
    end 

    describe "#fruits" do 
    it 'returns all fruit in the current round of ordering' do 
     expect(round.fruits).to match_array(testFruit) 
    end 
    end 

    describe "#next" do 
    it 'lets clears the list for the next round' do 
     round.next 

     expect(round.fruits).to match_array([]) 
    end 
    end 
end 

這使得利用let!功能的RSpec的,你可以讀到here。基本上,它確保您在每次測試之間獲得一致的設置。

最後,您不必擔心有關數據庫寫入的任何異步問題;直到從數據庫收到數據確實寫入成功的回覆,Rails纔會繼續。

+0

感謝您的回答,但我無法理解泄漏狀態有時會導致我的測試失敗。 –

+0

對不起,我現在看到,我的specs_helper中有'config.order =:random'。 –

+0

@RyderBergerud這正是推薦使用隨機測試順序的原因,因爲它突出了間歇性故障形式的泄漏狀態 –