2011-07-01 138 views
3

我在嘗試確定如何測試簡單計算關聯記錄中值的平均值的方法。我關心的是測試實現與返回的實際結果。如何在Ruby on Rails中使用Rspec測試鏈式方法

說我有以下型號...

class User 
    has_many :interviews 

    def interview_grade 
    interviews.average(:score).round unless interviews.empty? 
    end 
end 

class Interview 
    belongs_to :user 
end 

而在user_spec.rb我有...

​​

這些測試都通過了,但感覺脆弱的我。如果interview_grade實際上應該計算得分(例如)的總和。由於我只是測試一個特定的方法鏈被調用,所以這個通過測試不會告訴我結果實際上是不正確的。

我已經嘗試使用存根user.interviews來設置測試的可用分數,但由於關聯的延遲加載方式,這在Rails 3中似乎很棘手。即我不能只創建一個Interview對象數組,因爲它不響應平均method

任何建議非常感謝。

回答

1

說回這個在3年後沒有必要。我會以完全不同的方式處理它。

下面代碼的好處是,爲了編寫InterviewGrader的測試,我不再需要擔心分數是如何獲得的。

我只是給它的分數,並測試它給了我正確的輸出。

另外我絕不需要擔心InterviewGrader的底層實現。但是,如果邏輯在以後更改,測試將失敗。

User上的新scores方法需要單獨測試。

class InterviewGrader 

    def self.run scores 
    new(scores).run 
    end 

    attr_reader :scores 

    def initialize(scores) 
    @scores = scores 
    end 

    def run 
    scores.inject { |sum, score| 
     sum + score 
    }.to_f/number_of_scores 
    end 

    private 

    def number_of_scores 
    scores.length 
    end 

end 


class User 
    has_many :interviews 

    def scores 
    interviews.map(&:score) 
    end 

    def interview_grade 
    InterviewGrader.run(scores) 
    end 
end 

class Interview 
    belongs_to :user 
end 
0

這是不正確的使用stubbing和mocking的。

在這種情況下,您應該只測試一下,即interview_grade的工作原理,當average返回零(且這只是使用interviews.empty?的情況)。

average方法由rails自己測試。 round紅寶石測試方法(我猜)。所以你不需要測試這個方法。這是測試你自己的代碼的一般想法。

如果你想測試,如何計算interview_grade,你應該創建測試數據(與燈具或工廠)。因爲你應該單獨測試(在某些情況下)系統的一部分,在這種情況下,分離是錯誤的:interviews.average和interviews.empty?依賴於你的代碼,但在規範中它們是獨立的。

def interview_grade 
    interviews.average(:score).try(:round) 
end 

如果你重寫你的方法,這樣,你在磕碰和嘲諷

+0

我更喜歡使用這裏的嘗試,我沒有想到這一點。 但是,我試圖避免使用工廠,因爲它們很慢。 我寧願模擬user.interviews,但正如我在問題中提到的,由於關聯的延遲加載,我還沒有想出在Rails 3中這樣做的好方法。 –