Marnen E. Laibow-Koser
September 2010, revised June 2012
class Twitter
include HTTParty
def self.user_info(username, format = :json)
get "http://api.twitter.com/1/users/show/#{username}.#{format}"
end
end
Call the external service and make sure we’re processing the result
describe Twitter do
describe "user_info" do
it "should get extended user information" do
Twitter.user_info('marnen')['name'].should == "Marnen Laibow-Koser"
end
end
end
WRONG!
describe Twitter do
describe "user_info" do
it "should get extended user information" do
Twitter.user_info('marnen')['name'].should == "Marnen Laibow-Koser"
end
end
end
http://github.com/bblimke/webmock
gem install webmock
spec/spec_helper
require 'webmock/rspec' Spec::Runner.configure do |config| config.include WebMock end
features/support/env.rb
require 'webmock/rspec' module WebMockWorld include WebMock include WebMock::Matchers end World(WebMockWorld)
(Works with Test::Unit too.)
stub_request(:get, "www.example.com").to_return(:body => "My canned response")
stub_request(:post, "www.example.com").with(:query => {'name' => 'marnen'})
stub_request(:any, /^www\.example\.(com|net|org)/)
curl -is http://api.twitter.com/1/users/show/marnen.json > canned_response.json
canned_response.json
HTTP/1.1 200 OK
{"screen_name":"marnen", "name":"Marnen Laibow-Koser", ...}
describe Twitter do
describe "user_info" do
it "should get extended user information" do
canned_response = File.new 'canned_response.json'
stub_request(:get, "api.twitter.com/1/users/show/marnen.json").to_return(canned_response)
Twitter.user_info('marnen')['name'].should == "Marnen Laibow-Koser"
end
end
end
It’s tedious to use curl to get all those canned responses. Fortunately, we don’t have to.
https://github.com/myronmarston/vcr
gem install vcr
Put this in a Cucumber support file (also works with RSpec and Test::Unit)
require 'vcr'
VCR.configure do |c|
c.cassette_library_dir = 'fixtures/vcr_cassettes'
c.hook_into :webmock
end
VCR.cucumber_tags do |t|
t.tag '@vcr', :use_scenario_name => true
end
Tag your scenarios with @vcr or call VCR directly in your steps
And then, just run your tests as normal—no more messing with curl!
:once:new_episodes:none:allVCR.use_cassette('dynamic', :erb => { :arg1 => 7, :arg2 => 'baz' })
No external calls means no external dependencies
No network overhead!
WebMock raises an exception if it doesn’t recognize an HTTP request
forbidden.json
HTTP/1.1 403 Forbidden
spec/models/twitter_spec.rb
describe Twitter do
it "should gracefully handle error conditions" do
stub_request(:any, /^api\.twitter\.com/).to_return(File.new 'forbidden.json')
lambda { Twitter.user_info('forbidden') }.should_not raise_error
end
end
http://github.com/bblimke/webmock
https://github.com/myronmarston/vcr