webmock 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/CHANGELOG.md +35 -0
  2. data/README.md +10 -24
  3. data/VERSION +1 -1
  4. data/lib/webmock.rb +4 -0
  5. data/lib/webmock/api.rb +1 -1
  6. data/lib/webmock/assertion_failure.rb +2 -4
  7. data/lib/webmock/cucumber.rb +8 -0
  8. data/lib/webmock/errors.rb +13 -1
  9. data/lib/webmock/http_lib_adapters/curb.rb +2 -2
  10. data/lib/webmock/http_lib_adapters/em_http_request.rb +31 -17
  11. data/lib/webmock/http_lib_adapters/httpclient.rb +3 -3
  12. data/lib/webmock/http_lib_adapters/net_http.rb +2 -2
  13. data/lib/webmock/http_lib_adapters/patron.rb +2 -2
  14. data/lib/webmock/request_execution_verifier.rb +18 -4
  15. data/lib/webmock/request_pattern.rb +1 -1
  16. data/lib/webmock/request_registry.rb +13 -28
  17. data/lib/webmock/request_signature.rb +15 -2
  18. data/lib/webmock/rspec.rb +32 -1
  19. data/lib/webmock/{adapters/rspec → rspec}/matchers.rb +4 -0
  20. data/lib/webmock/{adapters/rspec → rspec/matchers}/request_pattern_matcher.rb +0 -0
  21. data/lib/webmock/{adapters/rspec → rspec/matchers}/webmock_matcher.rb +0 -0
  22. data/lib/webmock/stub_registry.rb +43 -0
  23. data/lib/webmock/stub_request_snippet.rb +27 -0
  24. data/lib/webmock/test_unit.rb +20 -1
  25. data/lib/webmock/util/hash_counter.rb +9 -4
  26. data/lib/webmock/util/hash_keys_stringifier.rb +23 -0
  27. data/lib/webmock/webmock.rb +14 -4
  28. data/spec/curb_spec.rb +1 -1
  29. data/spec/curb_spec_helper.rb +0 -4
  30. data/spec/em_http_request_spec.rb +5 -0
  31. data/spec/em_http_request_spec_helper.rb +0 -4
  32. data/spec/errors_spec.rb +17 -0
  33. data/spec/httpclient_spec_helper.rb +0 -4
  34. data/spec/net_http_spec_helper.rb +2 -8
  35. data/spec/patron_spec_helper.rb +4 -11
  36. data/spec/request_execution_verifier_spec.rb +14 -4
  37. data/spec/request_registry_spec.rb +29 -80
  38. data/spec/request_signature_spec.rb +77 -3
  39. data/spec/spec_helper.rb +0 -18
  40. data/spec/stub_registry_spec.rb +86 -0
  41. data/spec/stub_request_snippet_spec.rb +47 -0
  42. data/spec/util/hash_counter_spec.rb +15 -0
  43. data/spec/util/hash_keys_stringifier_spec.rb +27 -0
  44. data/spec/webmock_shared.rb +63 -66
  45. data/test/test_helper.rb +5 -1
  46. data/test/test_webmock.rb +5 -2
  47. data/webmock.gemspec +17 -7
  48. metadata +19 -9
  49. data/lib/webmock/adapters/rspec.rb +0 -33
  50. data/lib/webmock/adapters/test_unit.rb +0 -19
@@ -2,7 +2,8 @@ module WebMock
2
2
 
3
3
  class RequestSignature
4
4
 
5
- attr_accessor :method, :uri, :body, :headers
5
+ attr_accessor :method, :uri, :body
6
+ attr_reader :headers
6
7
 
7
8
  def initialize(method, uri, options = {})
8
9
  self.method = method
@@ -20,11 +21,23 @@ module WebMock
20
21
  string
21
22
  end
22
23
 
24
+ def headers=(headers)
25
+ @headers = WebMock::Util::Headers.normalize_headers(headers)
26
+ end
27
+
28
+ def hash
29
+ self.to_s.hash
30
+ end
31
+
32
+ def eql?(other)
33
+ self.to_s == other.to_s
34
+ end
35
+
23
36
  private
24
37
 
25
38
  def assign_options(options)
26
39
  self.body = options[:body] if options.has_key?(:body)
27
- self.headers = WebMock::Util::Headers.normalize_headers(options[:headers]) if options.has_key?(:headers)
40
+ self.headers = options[:headers] if options.has_key?(:headers)
28
41
  end
29
42
 
30
43
  end
@@ -1 +1,32 @@
1
- require File.join(File.dirname(__FILE__), "adapters/rspec")
1
+ require 'webmock'
2
+
3
+ # RSpec 1.x and 2.x compatibility
4
+ if defined?(RSpec)
5
+ RSPEC_NAMESPACE = RSPEC_CONFIGURER = RSpec
6
+ elsif defined?(Spec)
7
+ RSPEC_NAMESPACE = Spec
8
+ RSPEC_CONFIGURER = Spec::Runner
9
+ else
10
+ begin
11
+ require 'rspec'
12
+ RSPEC_NAMESPACE = RSPEC_CONFIGURER = RSpec
13
+ rescue LoadError
14
+ require 'spec'
15
+ RSPEC_NAMESPACE = Spec
16
+ RSPEC_CONFIGURER = Spec::Runner
17
+ end
18
+ end
19
+
20
+ require 'webmock/rspec/matchers'
21
+
22
+ RSPEC_CONFIGURER.configure { |config|
23
+
24
+ config.include WebMock::API
25
+ config.include WebMock::Matchers
26
+
27
+ config.after(:each) do
28
+ WebMock.reset!
29
+ end
30
+ }
31
+
32
+ WebMock::AssertionFailure.error_class = RSPEC_NAMESPACE::Expectations::ExpectationNotMetError
@@ -1,3 +1,7 @@
1
+ require 'webmock'
2
+ require 'webmock/rspec/matchers/request_pattern_matcher'
3
+ require 'webmock/rspec/matchers/webmock_matcher'
4
+
1
5
  module WebMock
2
6
  module Matchers
3
7
  def have_been_made
@@ -0,0 +1,43 @@
1
+ module WebMock
2
+
3
+ class StubRegistry
4
+ include Singleton
5
+
6
+ attr_accessor :request_stubs
7
+
8
+ def initialize
9
+ reset!
10
+ end
11
+
12
+ def reset!
13
+ self.request_stubs = []
14
+ end
15
+
16
+ def register_request_stub(stub)
17
+ request_stubs.insert(0, stub)
18
+ stub
19
+ end
20
+
21
+ def registered_request?(request_signature)
22
+ request_stub_for(request_signature)
23
+ end
24
+
25
+ def response_for_request(request_signature)
26
+ stub = request_stub_for(request_signature)
27
+ stub ? evaluate_response_for_request(stub.response, request_signature) : nil
28
+ end
29
+
30
+ private
31
+
32
+ def request_stub_for(request_signature)
33
+ request_stubs.detect { |registered_request_stub|
34
+ registered_request_stub.request_pattern.matches?(request_signature)
35
+ }
36
+ end
37
+
38
+ def evaluate_response_for_request(response, request_signature)
39
+ response.evaluate(request_signature)
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,27 @@
1
+ module WebMock
2
+ class StubRequestSnippet
3
+ def initialize(request_signature)
4
+ @request_signature = request_signature
5
+ end
6
+
7
+ def to_s
8
+ string = "stub_request(:#{@request_signature.method},"
9
+ string << " \"#{WebMock::Util::URI.strip_default_port_from_uri_string(@request_signature.uri.to_s)}\")"
10
+
11
+ with = ""
12
+
13
+ if (@request_signature.body.to_s != '')
14
+ with << ":body => #{@request_signature.body.inspect}"
15
+ end
16
+
17
+ if (@request_signature.headers && !@request_signature.headers.empty?)
18
+ with << ", \n " unless with.empty?
19
+
20
+ with << ":headers => #{WebMock::Util::Headers.sorted_headers_string(@request_signature.headers)}"
21
+ end
22
+ string << ".\n with(#{with})" unless with.empty?
23
+ string << ".\n to_return(:status => 200, :body => \"\", :headers => {})"
24
+ string
25
+ end
26
+ end
27
+ end
@@ -1 +1,20 @@
1
- require File.join(File.dirname(__FILE__), "adapters/test_unit")
1
+ require 'test/unit'
2
+ require 'webmock'
3
+
4
+ module Test
5
+ module Unit
6
+ class TestCase
7
+ include WebMock::API
8
+
9
+ alias_method :teardown_without_webmock, :teardown
10
+ def teardown_with_webmock
11
+ teardown_without_webmock
12
+ WebMock.reset!
13
+ end
14
+ alias_method :teardown, :teardown_with_webmock
15
+
16
+ end
17
+ end
18
+ end
19
+
20
+ WebMock::AssertionFailure.error_class = Test::Unit::AssertionFailedError rescue MiniTest::Assertion # ruby1.9 compat
@@ -1,20 +1,25 @@
1
1
  module WebMock
2
-
3
2
  module Util
4
-
5
3
  class Util::HashCounter
6
4
  attr_accessor :hash
7
5
  def initialize
8
6
  self.hash = {}
7
+ @order = {}
8
+ @max = 0
9
9
  end
10
10
  def put key, num=1
11
11
  hash[key] = (hash[key] || 0) + num
12
+ @order[key] = @max = @max + 1
12
13
  end
13
14
  def get key
14
15
  hash[key] || 0
15
16
  end
16
- end
17
17
 
18
+ def each(&block)
19
+ @order.to_a.sort {|a, b| a[1] <=> b[1]}.each do |a|
20
+ block.call(a[0], hash[a[0]])
21
+ end
22
+ end
23
+ end
18
24
  end
19
-
20
25
  end
@@ -0,0 +1,23 @@
1
+ module WebMock
2
+ module Util
3
+ class HashKeysStringifier
4
+
5
+ def self.stringify_keys!(arg)
6
+ case arg
7
+ when Array
8
+ arg.map { |elem| stringify_keys!(elem) }
9
+ when Hash
10
+ Hash[
11
+ *arg.map { |key, value|
12
+ k = key.is_a?(Symbol) ? key.to_s : key
13
+ v = stringify_keys!(value)
14
+ [k,v]
15
+ }.inject([]) {|r,x| r + x}]
16
+ else
17
+ arg
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -48,20 +48,30 @@ module WebMock
48
48
  Config.instance.allow && Config.instance.allow.include?(uri.host)
49
49
  end
50
50
 
51
+ def self.reset!
52
+ WebMock::RequestRegistry.instance.reset!
53
+ WebMock::StubRegistry.instance.reset!
54
+ end
55
+
51
56
  def self.reset_webmock
52
- WebMock::RequestRegistry.instance.reset_webmock
57
+ WebMock::Deprecation.warning("WebMock.reset_webmock is deprecated. Please use WebMock.reset! method instead")
58
+ reset!
53
59
  end
54
-
60
+
55
61
  def self.reset_callbacks
56
62
  WebMock::CallbackRegistry.reset
57
63
  end
58
64
 
59
65
  def self.after_request(options={}, &block)
60
- CallbackRegistry.add_callback(options, block)
66
+ WebMock::CallbackRegistry.add_callback(options, block)
61
67
  end
62
68
 
63
69
  def self.registered_request?(request_signature)
64
- RequestRegistry.instance.registered_request?(request_signature)
70
+ WebMock::StubRegistry.instance.registered_request?(request_signature)
71
+ end
72
+
73
+ def self.print_executed_requests
74
+ puts WebMock::RequestExecutionVerifier.executed_requests_message
65
75
  end
66
76
 
67
77
  %w(
@@ -21,7 +21,7 @@ unless RUBY_PLATFORM =~ /java/
21
21
  describe "Curb features" do
22
22
  before(:each) do
23
23
  WebMock.disable_net_connect!
24
- WebMock::RequestRegistry.instance.reset_webmock
24
+ WebMock.reset!
25
25
  end
26
26
 
27
27
  describe "callbacks" do
@@ -30,10 +30,6 @@ module CurbSpecHelper
30
30
  curl
31
31
  end
32
32
 
33
- def default_client_request_headers(request_method = nil, has_body = false)
34
- nil
35
- end
36
-
37
33
  def client_timeout_exception_class
38
34
  Curl::Err::TimeoutError
39
35
  end
@@ -25,5 +25,10 @@ unless RUBY_PLATFORM =~ /java/
25
25
  http_request(:get, "http://www.example.com/?x=3", :query => {"a" => ["b", "c"]}).body.should == "abc"
26
26
  end
27
27
 
28
+ it "should work with optional query params declared as string" do
29
+ stub_http_request(:get, "www.example.com/?x=3&a[]=b&a[]=c").to_return(:body => "abc")
30
+ http_request(:get, "http://www.example.com/?x=3", :query => "a[]=b&a[]=c").body.should == "abc"
31
+ end
32
+
28
33
  end
29
34
  end
@@ -47,10 +47,6 @@ module EMHttpRequestSpecHelper
47
47
  ""
48
48
  end
49
49
 
50
- def default_client_request_headers(request_method = nil, has_body = false)
51
- nil
52
- end
53
-
54
50
  def setup_expectations_for_real_request(options = {})
55
51
  end
56
52
 
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "errors" do
4
+ describe WebMock::NetConnectNotAllowedError do
5
+ describe "message" do
6
+ it "should have message with request signature and snippet" do
7
+ request_signature = mock(:to_s => "aaa")
8
+ WebMock::StubRequestSnippet.stub!(:new).
9
+ with(request_signature).and_return(mock(:to_s => "bbb"))
10
+ expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
11
+ "\n\nYou can stub this request with the following snippet:\n\n" +
12
+ "bbb\n\n============================================================"
13
+ WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
14
+ end
15
+ end
16
+ end
17
+ end
@@ -41,10 +41,6 @@ module HTTPClientSpecHelper
41
41
  Errno::ECONNREFUSED
42
42
  end
43
43
 
44
- def default_client_request_headers(request_method = nil, has_body = false)
45
- {'Content-Type'=>'application/x-www-form-urlencoded'} if request_method == 'POST' && has_body
46
- end
47
-
48
44
  def setup_expectations_for_real_request(options = {})
49
45
  socket = mock("TCPSocket")
50
46
  TCPSocket.should_receive(:new).
@@ -22,7 +22,8 @@ module NetHTTPSpecHelper
22
22
  http = Net::HTTP.new(uri.host, uri.port)
23
23
  if uri.scheme == "https"
24
24
  http.use_ssl = true
25
- http.ssl_timeout = 10
25
+ #1.9.1 has a bug with ssl_timeout
26
+ http.ssl_timeout = 10 unless RUBY_VERSION == "1.9.1"
26
27
  end
27
28
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
28
29
  response = http.start {|http|
@@ -38,13 +39,6 @@ module NetHTTPSpecHelper
38
39
  })
39
40
  end
40
41
 
41
- def default_client_request_headers(request_method = nil, has_body = false)
42
- default_request = Net::HTTPGenericRequest.new('','','','/')
43
- default_net_http_headers = Hash[*default_request.to_hash.map {|k,v|
44
- [k, v.flatten]
45
- }.flatten]
46
- end
47
-
48
42
  def client_timeout_exception_class
49
43
  Timeout::Error
50
44
  end
@@ -1,15 +1,16 @@
1
+ require 'ostruct'
2
+
1
3
  module PatronSpecHelper
2
4
  def http_request(method, uri, options = {}, &block)
3
5
  uri = Addressable::URI.heuristic_parse(uri)
4
6
  sess = Patron::Session.new
5
- sess.base_url = "#{uri.omit(:userinfo, :query).normalize.to_s}".gsub(/\/$/,"")
6
-
7
+ sess.base_url = "#{uri.omit(:userinfo, :path, :query).normalize.to_s}".gsub(/\/$/,"")
7
8
  sess.username = uri.user
8
9
  sess.password = uri.password
9
10
 
10
11
  sess.connect_timeout = 10
11
12
  sess.timeout = 10
12
-
13
+
13
14
  response = sess.request(method, "#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", options[:headers] || {}, {
14
15
  :data => options[:body]
15
16
  })
@@ -28,14 +29,6 @@ module PatronSpecHelper
28
29
  })
29
30
  end
30
31
 
31
- def default_client_request_headers(request_method = nil, has_body = false)
32
- if Patron.version >= "0.4.6"
33
- {'Expect'=>''}
34
- else
35
- nil
36
- end
37
- end
38
-
39
32
  def client_timeout_exception_class
40
33
  Patron::TimeoutError
41
34
  end
@@ -5,6 +5,8 @@ describe WebMock::RequestExecutionVerifier do
5
5
  @verifier = WebMock::RequestExecutionVerifier.new
6
6
  @request_pattern = mock(WebMock::RequestPattern, :to_s => "www.example.com")
7
7
  @verifier.request_pattern = @request_pattern
8
+ WebMock::RequestRegistry.instance.stub(:to_s).and_return("executed requests")
9
+ @executed_requests_info = "\n\nThe following requests were made:\n\nexecuted requests\n" + "="*60
8
10
  end
9
11
 
10
12
 
@@ -13,13 +15,17 @@ describe WebMock::RequestExecutionVerifier do
13
15
  it "should report failure message" do
14
16
  @verifier.times_executed = 0
15
17
  @verifier.expected_times_executed = 2
16
- @verifier.failure_message.should == "The request www.example.com was expected to execute 2 times but it executed 0 times"
18
+ expected_text = "The request www.example.com was expected to execute 2 times but it executed 0 times"
19
+ expected_text << @executed_requests_info
20
+ @verifier.failure_message.should == expected_text
17
21
  end
18
22
 
19
23
  it "should report failure message correctly when executed times is one" do
20
24
  @verifier.times_executed = 1
21
25
  @verifier.expected_times_executed = 1
22
- @verifier.failure_message.should == "The request www.example.com was expected to execute 1 time but it executed 1 time"
26
+ expected_text = "The request www.example.com was expected to execute 1 time but it executed 1 time"
27
+ expected_text << @executed_requests_info
28
+ @verifier.failure_message.should == expected_text
23
29
  end
24
30
 
25
31
  end
@@ -29,12 +35,16 @@ describe WebMock::RequestExecutionVerifier do
29
35
  it "should report failure message if it executed number of times specified" do
30
36
  @verifier.times_executed = 2
31
37
  @verifier.expected_times_executed = 2
32
- @verifier.negative_failure_message.should == "The request www.example.com was not expected to execute 2 times but it executed 2 times"
38
+ expected_text = "The request www.example.com was not expected to execute 2 times but it executed 2 times"
39
+ expected_text << @executed_requests_info
40
+ @verifier.negative_failure_message.should == expected_text
33
41
  end
34
42
 
35
43
  it "should report failure message when not expected request but it executed" do
36
44
  @verifier.times_executed = 1
37
- @verifier.negative_failure_message.should == "The request www.example.com was expected to execute 0 times but it executed 1 time"
45
+ expected_text = "The request www.example.com was expected to execute 0 times but it executed 1 time"
46
+ expected_text << @executed_requests_info
47
+ @verifier.negative_failure_message.should == expected_text
38
48
  end
39
49
 
40
50
  end