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

Popular posts from this blog

c# - SharpSVN - How to get the previous revision? -

c++ - Is it possible to compile a VST on linux? -

url - Querystring manipulation of email Address in PHP -