TDD of HTTP Clients With WebMock
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

TDD of HTTP Clients With WebMock

  • 9,047 views
Uploaded on

My presentation about Test Driven Development of HTTP clients using WebMock, presented at RubyManor 2. ...

My presentation about Test Driven Development of HTTP clients using WebMock, presented at RubyManor 2.
WebMock is a library for stubbing and setting expectations on HTTP requests in Ruby.

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
9,047
On Slideshare
9,012
From Embeds
35
Number of Embeds
4

Actions

Shares
Downloads
57
Comments
2
Likes
5

Embeds 35

http://www.slideshare.net 22
http://speakerrate.com 7
http://lanyrd.com 5
https://www.docsnode.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • Hi. I&#x2019;m Bartosz Blimke. I&#x2019;m work for New Bamboo, a development shop. We are working in a rigorous agile environment and we also offer agile coaching. <br /> I&#x2019;ve been working in Extreme Programming environments for the last 5 years, on small projects as well as on very big corporate projects. <br /> <br /> One of the code XP practices is ....
  • is test driven development. I&#x2019;m doing TDD for about 3 or 4 years now.
  • none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features
  • none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features
  • none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features
  • none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features

Transcript

  • 1. TDD of HTTP Clients with WebMock Bartosz Blimke @bartoszblimke new bamboo
  • 2. Test TDD RED RED Code new bamboo
  • 3. Hello http://my.geoservice.org Give me location for zip code WC1H 9EF GET http://my.geoservice.org/?zip=WC1H 9EF HTTP 200 - OK Content-Type: application/json Here is your location: {"latitude"=>"51.52","longitude":-0.12"} new bamboo
  • 4. describe GeoCoordinatesFinder do it "should make http request to geocoding service" do end it "should report coordinates provided by geocoding service" do end end new bamboo
  • 5. describe GeoCoordinatesFinder do it "should make http request to geocoding service" do ??? end it "should report coordinates provided by geocoding service" do ??? end end new bamboo
  • 6. new bamboo
  • 7. new bamboo
  • 8. class GeoCoordinatesFinder def get_coordinates_by_zip_code(zip) res = Net::HTTP.start("my.geoservice.org", 80) { |http| http.get("/?zip=#{URI.encode(zip)}") } result = JSON.parse(res) [result['latitude'], result['longitude']] end end new bamboo
  • 9. describe GeoCoordinatesFinder do before(:each) do @coordinates_finder = GeoCoordinatesFinder.new @mock_http = mock("http") @res = mock(Net::HTTPOK, :body => "{"latitude":"5.5","longitude":"6.6"}") Net::HTTP.stub!(:start).with("my.geoservice.org", 80).and_yield @mock_http @mock_http.stub!(:get).with("/?zip=WC1H%209EF").and_return(@res) end it "should make http request to geocoding service" do Net::HTTP.should_receive(:start).and_yield @mock_http @mock_http.should_receive(:get).with("/?zip=WC1H%209EF") @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") end it "should report coordinates provided by geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").should == ["5.5", "6.6"] end end new bamboo
  • 10. new bamboo
  • 11. class GeoCoordinatesFinder def get_coordinates_by_zip_code(zip) url = "http://my.geoservice.org?zip=#{URI.encode(zip)}" response = RestClient.get(url) result = JSON.parse(response) [result['latitude'], result['longitude']] end end new bamboo
  • 12. new bamboo
  • 13. describe GeoCoordinatesFinder do before(:each) do @coordinates_finder = GeoCoordinatesFinder.new RestClient.stub!(:get).with("http://my.geoservice.org?zip=WC1H%209EF"). and_return("{"latitude":"5.5","longitude":"6.6"}") end it "should make http request to yahoo geocoding service" do RestClient.should_receive(:get).with("http://my.geoservice.org?zip=WC1H%209EF") @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") end it "should report coordinates provided by geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").should == ["5.5", "6.6"] end end new bamboo
  • 14. I wanted a tool for stubbing HTTP requests that...
  • 15. I wanted a tool for stubbing HTTP requests that... • doesn’t depend on usage of a specific API
  • 16. I wanted a tool for stubbing HTTP requests that... • doesn’t depend on usage of a specific API • supports stubbing based on request method, uri, body and headers
  • 17. I wanted a tool for stubbing HTTP requests that... • doesn’t depend on usage of a specific API • supports stubbing based on request method, uri, body and headers • verifies expectations of requests
  • 18. I wanted a tool for stubbing HTTP requests that... • doesn’t depend on usage of a specific API • supports stubbing based on request method, uri, body and headers • verifies expectations of requests • supports different HTTP libraries
  • 19. WebMock new bamboo
  • 20. require 'webmock/rspec' include WebMock describe GeoCoordinatesFinder do before(:each) do @coordinates_finder = GeoCoordinatesFinder.new stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF"). to_return(:body => "{"latitude":"5.5","longitude":"6.6"}") end it "should make http request to geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") WebMock.should have_requested(:get, "http://my.geoservice.org?zip=WC1H 9EF") end it "should report coordinates provided by geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF"). should == ["5.5", "6.6"] end end new bamboo
  • 21. require 'webmock/rspec' include WebMock describe GeoCoordinatesFinder do before(:each) do @coordinates_finder = GeoCoordinatesFinder.new stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF"). to_return(:body => "{"latitude":"5.5","longitude":"6.6"}") end it "should make http request to geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") WebMock.should have_requested(:get, "http://my.geoservice.org?zip=WC1H 9EF") end it "should report coordinates provided by geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF"). should == ["5.5", "6.6"] end end new bamboo
  • 22. require 'webmock/rspec' include WebMock describe GeoCoordinatesFinder do before(:each) do @coordinates_finder = GeoCoordinatesFinder.new stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF"). to_return(:body => "{"latitude":"5.5","longitude":"6.6"}") end it "should make http request to geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") WebMock.should have_requested(:get, "http://my.geoservice.org?zip=WC1H 9EF") end it "should report coordinates provided by geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF"). should == ["5.5", "6.6"] end end new bamboo
  • 23. require 'webmock/rspec' include WebMock describe GeoCoordinatesFinder do before(:each) do @coordinates_finder = GeoCoordinatesFinder.new stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF"). to_return(:body => "{"latitude":"5.5","longitude":"6.6"}") end it "should make http request to geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") request(:get, "http://my.geoservice.org?zip=WC1H 9EF").should have_been_made end it "should report coordinates provided by geocoding service" do @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF"). should == ["5.5", "6.6"] end end new bamboo
  • 24. new bamboo
  • 25. class GeoCoordinatesFinder def get_coordinates_by_zip_code(zip) uri = "http://my_geoservice.org?zip=#{URI.encode(zip)}" result = JSON.parse(HTTPClient.new.get(uri).content) [result['latitude'], result['longitude']] end end new bamboo
  • 26. new bamboo
  • 27. Test::Unit require 'webmock/test_unit' include WebMock class TestGeoCoordinatesFinder < Test::Unit::TestCase def setup @coordinates_finder = GeoCoordinatesFinder.new stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF"). to_return(:body => "{"latitude":"5.5","longitude":"6.6"}") end def test_making_request_to_geocoding_service @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") assert_requested :get, "http://my.geoservice.org?zip=WC1H 9EF" end def test_reporting_coordinates_provided_by_geocoding_service assert_equal @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF"), ["5.5", "6.6"] end end new bamboo
  • 28. Test::Unit require 'webmock/test_unit' include WebMock class TestGeoCoordinatesFinder < Test::Unit::TestCase def setup @coordinates_finder = GeoCoordinatesFinder.new stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF"). to_return(:body => "{"latitude":"5.5","longitude":"6.6"}") end def test_making_request_to_geocoding_service @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF") assert_requested :get, "http://my.geoservice.org?zip=WC1H 9EF" end def test_reporting_coordinates_provided_by_geocoding_service assert_equal @coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF"), ["5.5", "6.6"] end end new bamboo
  • 29. Cucumber features/common/env.rb require 'webmock' include WebMock Before do WebMock.disable_net_connect! WebMock.reset_webmock end new bamboo
  • 30. Cucumber features/finding_geo_coordinates.feature Feature: Finding the way to an awesome conference In order to find the best way to Ruby Manor As a ruby geek I want to see how to get there on a map Scenario: User finds zip code coordinates on a map Given geoservice reports coordinates "51.52, -0.12" for zip code "WC1H 9EF" When I type "WC1H 9EF" into zip code field And I press "Show on map" Then I should see map centered at latitude "51.52" and longitude "-0.12" new bamboo
  • 31. Cucumber features/step_definitions/geocoding_service_steps.rb Given /^geoservice reports (.+), (.+) as coordinates for zip code (.+)$/ do |lat, long, zip_code| stub_request(:get, "http://my.geoservice.org?zip=#{zip_code}"). to_return( :body => "{"latitude":"#{lat}","longitude":"#{long}"}" ) end new bamboo
  • 32. Matching Requests on Body and Headers stub_request(:post, "www.example.net"). with(:body => "abc", :headers => { :content_type => 'text/plain' }) RestClient.post "www.example.net", "abc", :content_type => 'text/plain' WebMock.should have_requested(:post, "www.example.net"). with(:body => "abc", :headers => { 'Content-Type' => 'text/plain' }) new bamboo
  • 33. Smart URI Matching www.example.net/my path?x=my params new bamboo
  • 34. Smart URI Matching www.example.net/my path?x=my params www.example.net/my%20path?x=my%20params www.example.net:80/my path?x=my params www.example.net:80/my%20path?x=my%20params http://www.example.net/my path?x=my params http://www.example.net/my%20path?x=my%20params http://www.example.net:80/my path?x=my params http://www.example.net:80/my%20path?x=my%20params new bamboo
  • 35. Matching URIs with Regexp stub_request(:post, /example/). with(:body => "abc", :headers => { :content_type => 'text/plain' }) RestClient.post "www.example.net", "abc", :content_type => 'text/plain' WebMock.should have_requested(:post, /example/). with(:body => "abc", :headers => { 'Content-Type' => 'text/plain' }) new bamboo
  • 36. Basic Authentication stub_request(:any, 'user:pass@www.example.net'). to_return(:body => 'abc') RestClient::Resource.new( 'www.example.net', :user => 'user', :password => 'pass' ).post('abc') # ===> "abcn" WebMock.should have_requested(:post, 'user:pass@www.example.net') new bamboo
  • 37. Dynamic Responses stub_request(:any, 'www.example.net'). to_return(:body => lambda { |request| request.body }) RestClient.post('www.example.net', 'abc') # ===> "abcn" new bamboo
  • 38. Supported Libraries Net::HTTP HTTPClient new bamboo
  • 39. Supported Libraries Net::HTTP HTTPClient HTTParty RESTClient RightScale::HttpConnection open-uri new bamboo
  • 40. http://github.com/bblimke/webmock new bamboo
  • 41. http://github.com/bblimke/webmock http://groups.google.com/group/webmock-users new bamboo
  • 42. http://github.com/bblimke/webmock http://groups.google.com/group/webmock-users bartosz@new-bamboo.co.uk @bartoszblimke new bamboo
  • 43. Questions? http://github.com/bblimke/webmock http://groups.google.com/group/webmock-users bartosz@new-bamboo.co.uk @bartoszblimke new bamboo