testing - How to test chained methods in Ruby on Rails using Rspec -
i'm trying decide how test method calculates average of values on associated records. i'm concerned testing implementation vs actual result returned.
say have following models...
class user has_many :interviews def interview_grade interviews.average(:score).round unless interviews.empty? end end class interview belongs_to :user end
and in user_spec.rb
have...
describe "interview_grade" let(:user) {user.new} context "when user has interviews" before { user.stub_chain(:interviews, :empty?){false} } "should return average of appraisal ratings" user.interviews.should_receive(:average).with(:score).and_return(3.2) user.work_history_grade.should == 3 end end context "when user has no interviews" before {interview.destroy_all} "should return nil" user.interview_grade.should be_nil end end end
these tests pass feels fragile me. if interview_grade
should calculate sum of scores (for example). i'm testing particular chain of methods called, passing test wouldn't tell me result incorrect.
i have tried stubbing user.interviews
in order setup available scores test work seems tricky in rails 3 due way associations lazy loaded. i.e. can't create array of interview objects because doesn't respond average method
.
any advice appreciated.
coming 3 years later. would approach entirely differently.
the benefit of code below in order write tests interviewgrader no longer need worry how scores attained.
i give scores , test gives me correct output.
also never need worry underlying implementation of interviewgrader. however, if logic changed @ later date, tests fail.
the new scores
method on user
need tested separately.
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
Comments
Post a Comment