On Thu, Apr 28, 2011 at 8:03 PM, Pat Maddox <[email protected]> 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
> [email protected]
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users