Problems testing a destroy failure

Hello,
I’m trying to test an active record object destroy failure but I’m
having problems creating a failure situation. I have a before_filter
method called ‘require_user_payment_info’ which validates the
@payment_info object before the delete method is called so I can’t
create a ‘bad’ @payment_info object before the delete method is called.

Here’s the require_user_payment_info method:

  def require_user_payment_info
    @payment_info = credit_card_model.slave.find_by_user_guid(user_guid)
    if [email protected]_info || @payment_info.user_guid != user_guid
      redirect_to(:controller => 'store', :action => 'index') and return
false
    else
      if((@payment_info.card_expires_year.to_i < Date.today.year) ||
          ((@payment_info.card_expires_month.to_i < Date.today.month) &&
(@payment_info.card_expires_year.to_i == Date.today.year)))
        @payment_info.card_account_public = "" #clear this out so the
user is forced to re-enter the credit card number
        @payment_info.valid?
        flash.now[:error] = t('ui_flash_errors.card_expired_error')
      end
    end
  end

And the actual delete method:

  def delete
    # required to be called via a delete request
    redirect_to :action => 'edit' and return if !request.delete?
    if @payment_info.destroy
      flash[:notice] = "Delete SUCCESSFUL"
      redirect_to :action => 'new'
    else
      flash[:error] = "Delete failed"
      redirect_to :action => 'edit'
    end

Any ideas?

Thanks!

On Jan 5, 2014, at 2:06 PM, Clem R. wrote:

def require_user_payment_info
@payment_info.valid?
def delete
Shouldn’t this line be ‘def destroy’?

Delete is the method that is called without callbacks to actually remove
the record. Destroy calls up the before_destroy handlers and checks the
validations.

Here’s one ripped from a working application:

#group.rb
before_destroy :group_has_children?

private
def group_has_children?
errors.add(:base, “Cannot delete a group with members”) unless
groupings.count == 0
errors.blank?
end

There’s probably a better way to do this, but this was how I settled on
it. I know there’s a way to do this with validations, too. Probably just
this:

validate :group_has_children?, :on => :destroy

def group_has_children?
errors.add(:base, “Cannot delete a group with members”) unless
groupings.count == 0
end

Walter

Walter - thanks for getting back to me on this.

First of all, I should have made this more clear - the delete action is
in the controller, not the model and the @payment_info model object is
using the destroy method.

To me, this method seems to be as straight forward as possible - you
attempt to destroy a verified active record object and if the destroy is
successful, then redirect to the the new action, if it fails display the
error and redirect to the edit method. I don’t see a logic problem
anywhere in this method so I’m not a big fan of trying to change the
method just to satisfy testing.

I should add that this is a rails 2.3.18 (sigh) app. I see what
you’re saying about this code not being as RESTfully optimal as it could
be but I feel that point is diverging off the original question: “how do
I get @payment_info.destroy to fail in a test?”

On Jan 6, 2014, at 10:56 AM, Clem R. wrote:

anywhere in this method so I’m not a big fan of trying to change the
method just to satisfy testing.

I’m hardly an expert here. I looked in a simple site I did a while back
using scaffold, since I don’t have my Rails 4 legs under me yet, and
scaffold maps the DELETE REST method to YourController::destroy. If
you’re using the generic routing, then the DELETE request will go to
destroy. Apologies if your routes are not the same as mine, and you’ve
already ruled this out.

Walter

On Monday, January 6, 2014 4:22:03 PM UTC, Ruby-Forum.com User wrote:

I should add that this is a rails 2.3.18 (sigh) app. I see what
you’re saying about this code not being as RESTfully optimal as it could
be but I feel that point is diverging off the original question: “how do
I get @payment_info.destroy to fail in a test?”

I would usually stub it (using mocha, rspec etc) to return/raise as
appropriate. Alternatively you could submit data that you know will fail
validation

Fred

That was my original attempt too but the require_user_payment_info
before_filter method checks for a valid payment_info object and will
redirect away from the delete method if the @payment_info object isn’t
valid. If I mock the @payment_info object to be invalid, it won’t
make it to the delete method.

I must admit my mocking knowledge isn’t very strong so my attempts at
mocking have been failures.

Here’s the before_filter configuration for require_user_payment_info:

before_filter :require_user_payment_info, :only => [:show, :edit,
:update, :delete]

On Monday, January 6, 2014 6:16:48 PM UTC, Ruby-Forum.com User wrote:

In which case you want to just stub out the destroy method. In rspec for
example you could do

PaymentInfo.any_instance.should_receive(:destroy).and_return(false)

And mocha can do something similar.

Fred

Bingo - that totally worked and here’s my solution:

def test_unsuccessful_delete
    payment_info = Factory.create(:payment_info, :user_guid=>@user.guid, 
:card_expires_month=>'04',
                                    :card_expires_year=>(Date.today.year+2).to_s, 
:cardholder_city=>"test city",
                                      :cardholder_state=>'NC', 
:cardholder_country=>'US', :cardholder_zip=>'27612')
    PaymentInfo.any_instance.stubs(:destroy).returns(false)

    delete(:delete, {}, @session)
    assert_response(:redirect)
    assert_equal false, assigns(:payment_info).blank?
    assert_redirected_to({:controller=>'account', :action=>'edit'})
    assert_equal flash[:error], "There was an error deleting your credit 
card information. Please try again."
  end

Thanks for your help!

Fred - big thanks on this. I’m going to give it a try shortly and get
back to you.