Forum: RSpec cucumber - when to stub/mock

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Matthew Van Horn (Guest)
on 2009-05-04 06:00
(Received via mailing list)
I'm just curious about this, since my solution involved stubbing a
call to GeoIp.

Is there a good rule of thumb for when you make exceptions to the 'no
stubbing' philosophy of Cucumber?

My step was: "Given I am accessing the site from Japan," but I can
think of other situations - mostly when interacting with web services,
that I'd probably want to stub something, rather than requiring a net
connection for testing.

thanks for any advice,
Matt Van Horn
Aslak H. (Guest)
on 2009-05-04 09:30
(Received via mailing list)
> I'm just curious about this, since my solution involved stubbing a call to
> GeoIp.
>
> Is there a good rule of thumb for when you make exceptions to the 'no
> stubbing' philosophy of Cucumber?
>

This is the rule of thumb:
http://wiki.github.com/aslakhellesoy/cucumber/mock...


> My step was: "Given I am accessing the site from Japan," but I can think of
> other situations - mostly when interacting with web services, that I'd
> probably want to stub something, rather than requiring a net connection for
> testing.
>

Your case might be special enough that the rule of thumb doesn't apply.
If
you explain in more detail what's going on I might be able to give some
more
advice on how to address it.

Aslak
Mike D. (Guest)
on 2009-05-04 09:57
(Received via mailing list)
On May 4, 2009, at 1:28 AM, aslak hellesoy wrote:

> Is there a good rule of thumb for when you make exceptions to the
> 'no stubbing' philosophy of Cucumber?
>
> This is the rule of thumb: 
http://wiki.github.com/aslakhellesoy/cucumber/mock...

I'm in a similar boat as Matt.  My app does geocoding using Andre
Lewis' excellent geokit gem (and the Rails plugin).  That stuff hits
web-based geocoders (Google in my case).  I also scrape other web sites.

So, in order to make my testing executable without a net connection
and avoid extra traffic on other folks' sites from my tests, I stub
out the actual net call with code like this:

def stub_geocode_lookup(address,datafile)
   @xml = File.read(RAILS_ROOT + "/spec/fixtures/geocodes/" + datafile)
   response = MockSuccess.new
   response.stubs(:body).returns(@xml)
   stub_google_call(address,response)
end

def stub_google_call(address,response)
   url = "http://maps.google.com/maps/geo?
q
=
#{Geokit
::Inflector
::url_escape
(address)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8"

Geokit
::Geocoders
::GoogleGeocoder
.stubs(:call_geocoder_service).with(url).returns(response)
end


I also make use of FakeWeb in a couple places to do a similar thing
for the scraping of sites.  I have a rake task that grabs fresh
versions of the pages I'm going to scrape and deposits it into my spec/
fixtures directory.  If I run that every couple of days, I reduce my
risk of having my fixture data diverge too far from what the
production app actually sees.

Mike D.
Mark W. (Guest)
on 2009-05-04 11:05
(Received via mailing list)
On Sun, May 3, 2009 at 10:42 PM, Mike D. <removed_email_address@domain.invalid> 
wrote:

>
> I also make use of FakeWeb in a couple places to do a similar thing for the
> scraping of sites.


FWIW, so does the maintainer of FakeWeb, Chris K. (with whom I
work).

Stubbing should be avoided when using Cucumber, if only because that
reduces
its effectiveness as an integration testing tool. That doesn't mean
stubbing
is prohibited. You don't really need to test Gooble. And Cucumber's
specing
and communication capabilities don't suffer from stubbing.

///ark
Kornelis S. (Guest)
on 2009-05-04 11:13
(Received via mailing list)
It's possibly worth pointing out for anyone else who needs to do
stubbing, that you don't necessarily need a framework to stub stuff; I
have cucumber tests that stub out some setup code in my app*, and they
just use monkey-patching to do the stubbing.

For instance, in the example below, you could just do:
module Geokit
  module Geocoders
    class GoogleGeocoder
      def call_geocoder_service(url)
        ... do whatever is needed to return appropriate test data
      end
    end
  end
end

You could even use alias_method to rename the original
call_geocoder_service and call it if it got an unexpected url.

I'm not sure which is better - this at least saves you from a
dependency on an external stubbing/mocking framework.  But it could be
seen as uglier.

- Korny
* I know, this is not ideal, but it's testing a one-off migration
script, and I didn't really want to make the script setup code
generic, just to make the tests cleaner.

On Mon, May 4, 2009 at 3:42 PM, Mike D. <removed_email_address@domain.invalid> 
wrote:
> excellent geokit gem (and the Rails plugin).  That stuff hits web-based
>  stub_google_call(address,response)
> scraping of sites.  I have a rake task that grabs fresh versions of the
>
--
Kornelis Sietsma  korny at my surname dot com
"Every jumbled pile of person has a thinking part
that wonders what the part that isn't thinking
isn't thinking of"
Aslak H. (Guest)
on 2009-05-04 11:16
(Received via mailing list)
> Stubbing should be avoided when using Cucumber, if only because that
> reduces its effectiveness as an integration testing tool. That doesn't mean
> stubbing is prohibited. You don't really need to test Gooble. And Cucumber's
> specing and communication capabilities don't suffer from stubbing.
>

One thing to be aware of when stubbing: There is no cleanup/revert logic
yet
in Cucumber. This means that if you stub a class method, it will remain
stubbed for subsequent scenarios. This means high risk of coupled
scenarios
and unpredictable behaviour if you run scenarios in different orders.

If you need a cleanup facility (remove stubbed methods after a
scenario),
please file a feature request.

Aslak
Matthew Van Horn (Guest)
on 2009-05-04 14:51
(Received via mailing list)
I followed Bryan's pattern here, and let RSpec reset everything.

http://www.brynary.com/2009/2/3/cucumber-step-defi...
Pat M. (Guest)
on 2009-05-05 20:43
(Received via mailing list)
Don't mock the Geolp library directly. Wrap it with an API that fits
your domain better. Then write a very simple object that implements
the same API but doesn't hit the network. You can use a switch
somewhere in env.rb to use your fake implementation or the Geolp one.

Pat
Bill K. (Guest)
on 2009-05-05 21:33
(Received via mailing list)
My absolute favorite solution for this:
http://github.com/chrisk/fakeweb/tree/master

I use that in an application I'm building that uses Twitter's OAuth,
and otherwise heavily uses the Twitter API. It allows me to easily
fake out all of Twitter's responses so I can do
unit/integration/acceptance tests (with Cucumber and WebRat for the
latter) without touching the network.

As a matter of good practice, I always do this first:

FakeWeb.allow_net_connect = false

That ensures that any outbound HTTP requests that I forgot to fake out
will cause FakeWeb to blow up in my face and let me know that I've
missed something rather than silently letting it go by.


On Tue, May 5, 2009 at 12:34 PM, Pat M. <removed_email_address@domain.invalid>
wrote:
>> Is there a good rule of thumb for when you make exceptions to the 'no stubbing' 
philosophy of Cucumber?
> _______________________________________________
> rspec-users mailing list
> removed_email_address@domain.invalid
> http://rubyforge.org/mailman/listinfo/rspec-users
>



--
Bill K.

http://bkocik.net
Matthew Van Horn (Guest)
on 2009-05-06 05:55
(Received via mailing list)
Actually, I do have my own object wrapping GeoIp, and I stubbed the
method on that object that returns a country code for me.
I can see maybe creating another object to be used in the test
environment, but I can't see what advantages that offers over using
the rspec mocking framework.
This topic is locked and can not be replied to.