views:

43

answers:

2

I am testing a simple password reset action and would like RSpec's "change" matcher for lambdas. But it doesn't work for this controller action. Everything works fine without that matcher. Here is the spec:

  describe "#update" do
it "Updates the password and resets the token" do
  @user = Factory :user
  getter = lambda{
    get :edit, :id => @user.perishable_token, :user => {:password_confirmation => "new_password",
                                                      :password => "new_password"}
    @user.reload
  }
  getter.should change(@user, :password)
  getter.should change(@user, :perishable_token)
end

it "Updates the password and resets the token" do
  @user = Factory :user
  old_password = @user.password
  old_token = @user.perishable_token
  get :edit, :id => @user.perishable_token, :user => {:password_confirmation => "new_password",
                                                      :password => "new_password"}        
  @user.reload.password.should != old_password
  @user.perishable_token.should != old_token
end
end

The second it-block works, the first one doesn't. I tried to print the values inside the lambda and they indeed aren't changed.

Thank you very much for any ideas on this issue!

A: 

You need to use call to actually execute the lambda in your first example. You assign the lambda to getter, but never do a getter.call to actually execute the lambda and get your result.

x1a4
The lambda already seems to get executed. I tried "getter.call" between the lambda definition and the expectations and nothing changed. Then I tried "getter.call.should change(@user, :password)" but got an error saying that User doesn't have a method 'call'. So I concluded that the lamda returned the last statement being @user.reload. That got confirmed by adding a print statement at the end of the lamda which got executed and the error message changed to undefined method 'call' for nil.
ajmurmann
A: 

So as it turns out the Change-matcher calls the proc. So that wasn't the problem. However, I was calling Edit and not Update. So nothing was supposed to change. In addition Password only exists on User objects where the password was just set and that where not retrieved from the DB since the clear text password is not saved. Here is the now working code:

describe "#update" do
it "Updates the password and resets the token" do
  @user = Factory.create :user
  getter = lambda{
    post :update, :id => @user.perishable_token, :user => {:password_confirmation => "new_password",
                                                            :password => "new_password"}
    @user.reload
  }
  getter.should change(@user, :crypted_password)
  getter.should change(@user, :perishable_token)
end
end

I thought it would turn out to be a silly error, but two in one...

ajmurmann