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
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users