I've been using rFeedParser lately to do a little feed parsing. One of the problems I ran into was trying to test the thing. Since there's network IO involved, I obviously want to get some mock action. In my first attempt I ended up having to modify rFeedParser's call to open to explicitly calling OpenURI.open so that I could mock it out with rspec like this:
OpenURI.should_receive(:open_uri).at_least(:once).with(feed_url, {
"Accept-encoding"=>"gzip, deflate",
"User-Agent"=>"Filterly +http://www.filterly.com",
"Accept"=>"application/atom+xml,application/rdf+xml,application/rss+xml,application/x-netcdf,application/xml;q=0.9,text/xml;q=0.2,*/*;q=0.1",
"A-IM"=>"feed"
}).and_return(*xml_mocks)
xml_mocks is an array of strings that hold the xml I want to return on my sequence of calls. As you can see it's ugly as hell and not that fun to use. Last night at the New York City Ruby meeting (known as nyc.rb) I got a little pointer from Bryan Helmkamp to a library called FakeWeb. I have no clue how this escaped my notice until now, but it makes things much cleaner and easier. FakeWeb is a library written by Blaine Cook for faking web requests. Grab it like so:
sudo gem install FakeWeb
Then have fun with it like so:
require 'fake_web'
require 'open-uri'
# from the contents of a file:
FakeWeb.register_uri("http://www.pauldix.net/", :file => "some_file.xml")
# or from the contents of a string:
FakeWeb.register_uri("http://www.pauldix.net/", :string => "foo")
# and boom:
open("http://www.pauldix.net").read # => "foo"
There's only one gotcha to look out for. When you call FakeWeb.register_uri, make sure that the uri you pass in has a slash at the end. Your call to open can include the slash or not, but if you don't register the uri with the slash, the faking won't actually happen.
thanks for the tip, I'm going to write mock for openid consumer and fake_web might get used well :-)
Posted by: Priit Tamboom | June 13, 2008 at 01:09 AM
The other gotcha is query strings. If the url you hit does not exactly match, it doesn't work. So even if you have the same url but query string params in a different order, it won't work. Just an FYI. It is a cool gem though. Used it on my mirrored gem for the tests.
Posted by: John Nunemaker | June 13, 2008 at 04:03 PM