On Fri, Apr 29, 2011 at 10:05 PM, Rodrigo Rosenfeld Rosas <
lboc...@yahoo.com.br> wrote:

>  Em 29-04-2011 13:15, David Kahn escreveu:
>
>
>
> 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
>
>
> That is what happens in Rspec behind the scenes:
>
> module A
>   def test
>      1
>   end
> end
>
> include A
>
> puts test # 1
> puts A.test # 1
> puts singleton_methods.include?(:test) # false
> puts A.singleton_methods.include?(:test) # false
>
> class << A
>    def test
>        2
>    def
> end
>
> puts test # 1
> puts A.test # 2
> puts singleton_methods.include?(:test) # false
> puts A.singleton_methods.include?(:test) # true
>
> If you don't know very much about singleton classes (some people call them
> anonymous classes), you can take a look at these articles:
>
> http://www.contextualdevelopment.com/articles/2008/ruby-singleton
> http://ola-bini.blogspot.com/2006/09/ruby-singleton-class.html
>
> Hope that helps understanding why you can't include a mocked module in your
> spec (actually you can, but it won't work as expected...)
>

Thanks Rodrigo... I think I see it. In the end I have discovered that if I
want to mock a module, rather than going directly I need to stub out methods
in the class I am testing which call the module and this seems to work,
otherwise (and I am not sure if this is exactly the case you are
explaining), but certainly it 'does not work as expected'.


>
> Cheers,
>
> Rodrigo.
>
>
> _______________________________________________
> 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