On Nov 23, 2011, at 3:33 PM, Patrick J. Collins wrote: > I wrote a test that looked like this: > > it "increases the user's reputation" do > lambda { @comment.update_attribute(:helpful, true) }.should > change(@seller.reload, > :reputation_score).by(Event.reputation_change_for(:mark_helpful))
The change matcher has several forms, including: lambda { ... }.should change(object, method).by(amount) lambda { ... }.should change { object.method }.by(amount) Your example uses the former, which results in the following (roughly): receiver = @seller.reload value_before = receiver.reputation_score { @comment.update_attribute(:helpful, true) }.call value_after = receiver.reputation_score (value_after - value_before).should eq(Event.reputation_change_for(:mark_helpful)) As you can see, @seller.reload is only evaluated once, and its reputation score is going to be the same both times. If you want @seller.reload eval'd before and after, then you have to use the block form: lambda { @comment.update_attribute(:helpful, true) }. should change {@seller.reload.reputation_score }. by(Event.reputation_change_for(:mark_helpful)) Tangent: this is testing two things - @seller.reputation_score and Event.reputation_change_for(:mark_helpful). If either is failing to work correctly, this example won't tell you which. I'd recommend sticking to literals in expectations: lambda { @comment.update_attribute(:helpful, true) }. should change {@seller.reload.reputation_score }.by(3) HTH, David > end > > And I am getting this error: > 1) Comment comments on posts marking a comment as helpful increases the > user's reputation > Failure/Error: lambda { @comment.update_attribute(:helpful, true) > }.should change(@seller.reload, > :reputation_score).by(Event.reputation_change_for(:mark_helpful)) > reputation_score should have been changed by 3, but was changed by 0 > > -- > > The way the actual code works is, I have a comment observer that does: > > def after_update(comment) > Event.create_for_user(comment.user, :mark_helpful) > end > > And event.rb does something like: > > def create_for_user(user, event_type) > create!(:user => user, :reputation_change => > Event::SCORES[event_type]) > end > > The user model has an before_save callback which does: > > def sum_points > self.reputation_score = events.sum(:reputation_change) > self.points = events.sum(:points_change) > end > > > --- > > Anyway, so this test fails, and I am not sure why... If I write it in a > slightly less-cool way: > > it "increases the user's reputation" do > @seller.reputation_score.should == 0 > @comment.update_attribute(:helpful, true) > @seller.reload.reputation_score.should == > Event.reputation_change_for(:mark_helpful) > end > > Then it passes... If I throw in a debugger statement in there and manually > call the code, the reputation_score does indeed increase...... So I am > confused why the lambda {}.change thing isn't working? > > Thanks. > > Patrick J. Collins > http://collinatorstudios.com _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users