On Thu, Apr 28, 2011 at 8:03 PM, Pat Maddox <patmad...@me.com> wrote:

> On Apr 28, 2011, at 4:37 PM, David Kahn wrote:
>
> > I am a bit new to mocking. I am trying to stub the
> ActiveMerchant::Billing::PaypalGateway#authorize method but not clear how to
> do it. This is my code and spec.
> >
> > This is the pertinent code:
> >
> > module Payment
> >   def gateway
> >     ActiveMerchant::Billing::PaypalGateway.new(
> >       ...
> >     )
> >   end
> >
> >   def authorize_payment(payment_info, associated_record_type,
> associated_record_id)
> >       gateway.authorize(payment_info.amount ......
> >   end
> >
> > I tried this:
> >
> ActiveMerchant::Billing::PaypalGateway.should_receive(:authorize).and_return(authorize_payment_success_response)
>
> This is setting an expectation on the PaypalGateway object (which is a
> class!). But when you call PaypalGateway.new, you get back an instance -
> which is where you want to set the expectation. So what you really need to
> stub is something that looks more like an instance...you'd start off with:
>
> gateway = stub('gateway')

gateway.should_receive(:authorize)
>
> and next you can either stub PaypalGateway.new:
> ActiveMerchant::Billing::PaypalGateway.stub(:new).and_return gateway
>
> or what I'd more likely do:
> Payment.stub(:gateway).and_return gateway
>


Thanks Pat, this worked great and I think helping get my head around doing
this.

 I do have one additional question... I am testing a module here, and
noticed that I had to both include the module (Payment) *and* in my spec
call Payment#authorize_payment to get things working with the stub.

It seems kind of strange as if I did not include the module at the top, then
I would get 'undefined method `authorize_payment' for Payment:Module' when
called in the spec, which makes sense. But what does not make sense is that
when I do include the Module at the top, I still have to call
Payment#authorize_payment and not just authorize_payment to get the stub to
take (the test passes in both cases, when not explicitly declaring
Payment#... the mock does not take).

So it seems that it is as if there are two versions of Payment module ---
one which is explicitly connected via the rspec stub, and the other which is
the native. Once I stub Payment explicitly, I must explicitly declare it on
my calls, otherwise it goes to the native code. Is this correct?

I thought if I just removed the line
'Payment.stub(:gateway).and_return(gateway)' that I would not have to call
Payment#authorize.... and instead use authorize... but again, in this case
the mock does not take.

Anyway, I have things working (as below), but interested in why this is so.

require 'spec_helper'
include Payment

describe Payment do

  before(:each) do
    gateway = stub('gateway')
    Payment.stub(:gateway).and_return(gateway)
    gateway.stub!(:authorize).and_return(gateway_authorize_success_response)
  end

  it "should authorize payment with paypal using a valid card" do
    response = Payment.authorize_payment(payment_info_success, 'Bet', 1000)
    ...
  end

I.E., why does this not hit the stub:

  it "should authorize payment with paypal using a valid card" do
    response = authorize_payment(payment_info_success, 'Bet', 1000)
    ...
  end


>
> either one will get you there.
>
> Pat
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to