What happens is that the user object is cached in the @practice variable, so a reboot is required when the user has been updated. You cannot do this with the current specification, but you might think about what you are actually testing. It seems strange to me that your specification is for the Practice model, but the statement should change { @practice.user.points }.by(20) really describes the behavior of the User.
I would personally dismember the Practice and User models a bit more in your specification and independently check their behavior.
describe "#marking_completed" do before do @practice.question_id = Question.find(:first, conditions: { diff: "2" }).id.to_s @practice.responses.create!(:question_id => @practice.question_id, :marked_results => [true,true,true,true]) @practice.save! end it "should calculate the points once the hard practice is done" do @practice.user.should_receive(:add_points).with(20).once @practice.marking_completed end end
Then I would add a separate test for the User model:
describe User do it 'should add specified points to a user' do lambda { subject.add_points(100) }.should change { subject.points }.by(100) end end
Another kind of side note is that it is not clear what Question.find returns, or why user points change to 20 in your test.
source share