2016-12-29 87 views
0

我試圖編寫一個失敗的Rspec測試。實際測試與更長的代碼相關聯,但是我將問題縮小到了正在測試的類方法。Rspec傳遞類方法,但實例方法失敗

這裏的測試中Rspec的:

context "For '.CASH.' as a stock" do 
    let!(:cash) { FactoryGirl.create(:stock, symbol: '.CASH.', name: 'cash', status: 'Available') } 

    describe "When update_stock runs on it" do 
    it "should still have an 'Available' status" do 
     # status should be 'Error' and test should fail 
     Stock.change_to_error 
     expect(cash.status).to eq('Available') 
    end 
    end 
end 

這在Stock.rb測試模型類方法:

def self.change_to_error 
    self.all.each do |stock| 
    stock.status = "Error" 
    stock.save 
    end 
end 

出於某種原因,這個通行證。但是,如果我改變了它使用的實例方法,它將無法像它應該:

如果stock_spec.rb改爲實例方法:

context "For '.CASH.' as a stock" do 
let!(:cash) { FactoryGirl.create(:stock, symbol: '.CASH.', name: 'cash', status: 'Available') } 

    describe "When update_stock runs on it" do 
    it "should still have an 'Available' status" do 
     # status should be 'Error' and test should fail 
     cash.change_to_error 
     expect(cash.status).to eq('Available') 
    end 
    end 
end 

如果stock.rb類的方法變成了一個實例方法:

def change_to_error 
    self.status = 'Error' 
    self.save 
end 

這會通過。不幸的是,我不得不使用類方法而不是實例方法,因爲我想更新數據庫中的所有股票。 「Change_to_error」方法就是解決問題的方法。有沒有人知道它爲什麼會在類應用失敗時作爲類方法傳遞?但它在使用實例方法時會失敗嗎?

實際上,發生的事情是類方法不會更改「現金」的狀態屬性,但實例方法確實如此。我不知道爲什麼會這樣。

僅供參考,我使用RSpec的護欄

+1

您可以嘗試將'stock.save'更改爲'stock.save!'嗎?如果有什麼不對,這會引發異常。 – 31piy

+0

我試過了。沒有幫助。其他想法? – HoodieOnRails

+0

嘗試使用'Stock.find_each {| stock | stock.update_column(:status,'錯誤')}'。 – 31piy

回答

1

解決方法:需要把'cash.reload「Stock.change_to_error」之後和期望前行。

當使用let!時,該對象在測試之前創建。更新對象外的基礎數據會導致實例過期。調用reload強制ActiveRecord從數據庫中刷新它。


當您使用let,RSpec的不叫你塊引用屬性只有在第一次,在這種情況下,cash。因此,在第一個示例中,您在沒有記錄的情況下運行change_to_error,然後檢查cash上的狀態,該記錄在expect的行上創建。在第二個示例中,創建了cash對象,然後更改爲錯誤。我建議使用拖尾日誌來確認(tail -f log/test.log

如果更改爲let!,RSpec將在每個示例運行前創建該對象。另一種替代方法是在您的示例中引用cash,然後在創建的所有記錄上調用change_to_error

+0

不幸的是,這並沒有奏效。即使我使用before循環並使用@cash的實例變量而不是let(:cash),它也不起作用。任何其他想法? – HoodieOnRails

+0

雖然這並沒有解決問題,但我確實意識到您的觀察在上面提供的代碼中是正確的。 – HoodieOnRails

+1

嘗試在檢查狀態之前重新加載「現金」。現在你使用let!了,模型被創建,你的類方法改變了底層模型,但你的'現金'實例可能仍然有緩存值。試試'cash.reload!'然後檢查狀態。 – mroach