webmock 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ module WebMock
2
+
3
+ class Request
4
+ attr_accessor :method, :uri, :body, :headers
5
+
6
+ def initialize(method, uri, options = {})
7
+ self.method = method
8
+ self.uri = uri.is_a?(Addressable::URI) ? uri : WebMock::Util::URI.normalize_uri(uri)
9
+ assign_options(options)
10
+ end
11
+
12
+ def to_s
13
+ string = "#{self.method.to_s.upcase} #{WebMock::Util::URI.strip_default_port_from_uri_string(self.uri.to_s)}"
14
+ string << " with body '#{body.to_s}'" if body && body.to_s != ''
15
+ if headers && !headers.empty?
16
+ string << " with headers #{WebMock::Util::Headers.normalize_headers(headers).inspect.gsub("\"","'")}"
17
+ end
18
+ string
19
+ end
20
+
21
+ private
22
+
23
+ def assign_options(options)
24
+ self.body = options[:body] if options.has_key?(:body)
25
+ self.headers = WebMock::Util::Headers.normalize_headers(options[:headers]) if options.has_key?(:headers)
26
+ end
27
+
28
+ end
29
+ end
@@ -1,28 +1,41 @@
1
1
  module WebMock
2
2
 
3
- class RequestProfile < Struct.new(:method, :uri, :body, :headers)
4
-
5
- def initialize(method, uri, body = nil, headers = nil)
6
- super
7
- self.uri = WebMock::Util::URI.normalize_uri(self.uri) unless self.uri.is_a?(Addressable::URI)
8
- self.headers = WebMock::Util::Headers.normalize_headers(self.headers)
9
- end
3
+ class RequestProfile < Request
10
4
 
11
5
  def with(options)
12
- self.body = options[:body] if options.has_key?(:body)
13
- self.headers = WebMock::Util::Headers.normalize_headers(options[:headers]) if options.has_key?(:headers)
6
+ assign_options(options)
14
7
  self
15
8
  end
9
+
10
+ def body=(body)
11
+ @body = Body.new(body)
12
+ end
13
+
14
+ class Body
15
+
16
+ attr_reader :data
17
+
18
+ def initialize(data)
19
+ @data = data
20
+ end
16
21
 
17
- def to_s
18
- string = "#{self.method.to_s.upcase} #{WebMock::Util::URI.strip_default_port_from_uri_string(self.uri.to_s)}"
19
- string << " with body '#{body}'" if body
20
- if headers && !headers.empty?
21
- string << " with headers #{WebMock::Util::Headers.normalize_headers(headers).inspect.gsub("\"","'")}"
22
+ def ==(other)
23
+ other = Body.new(other) unless other.is_a?(Body)
24
+ other.is_a?(Body) &&
25
+ (other.is_empty? && self.is_empty? || other.data == self.data)
22
26
  end
23
- string
27
+
28
+ def is_empty?
29
+ @data.nil? || @data == ""
30
+ end
31
+
32
+ def to_s
33
+ @data
34
+ end
35
+
24
36
  end
25
37
 
26
38
  end
27
39
 
40
+
28
41
  end
@@ -25,9 +25,9 @@ module WebMock
25
25
 
26
26
  def response_for_request(request_signature)
27
27
  stub = request_stub_for(request_signature)
28
- stub ? stub.response : nil
28
+ stub ? evaluate_response_for_request(stub.response, request_signature) : nil
29
29
  end
30
-
30
+
31
31
  def times_executed(request_profile)
32
32
  self.requested_signatures.hash.select { |request_signature, times_executed|
33
33
  request_signature.match(request_profile)
@@ -42,5 +42,15 @@ module WebMock
42
42
  }
43
43
  end
44
44
 
45
+ def evaluate_response_for_request(response, request_signature)
46
+ evaluated_response = response.dup
47
+ [:body, :headers].each do |attribute|
48
+ if response.options[attribute].is_a?(Proc)
49
+ evaluated_response.options[attribute] = response.options[attribute].call(request_signature)
50
+ end
51
+ end
52
+ evaluated_response
53
+ end
54
+
45
55
  end
46
56
  end
@@ -1,8 +1,9 @@
1
1
  module WebMock
2
2
 
3
- class RequestSignature < RequestProfile
3
+ class RequestSignature < Request
4
4
 
5
5
  def match(request_profile)
6
+ raise ArgumentError unless request_profile.is_a?(RequestProfile)
6
7
  match_method(request_profile) &&
7
8
  match_body(request_profile) &&
8
9
  match_headers(request_profile) &&
@@ -9,8 +9,7 @@ module WebMock
9
9
  end
10
10
 
11
11
  def with(params)
12
- @request_profile.body = params[:body]
13
- @request_profile.headers = Util::Headers.normalize_headers(params[:headers])
12
+ @request_profile.with(params)
14
13
  self
15
14
  end
16
15
 
@@ -1,24 +1,26 @@
1
1
  module WebMock
2
2
  class Response
3
+ attr_accessor :options
3
4
 
4
5
  def initialize(options = {})
5
6
  @options = options
7
+ @options[:headers] = Util::Headers.normalize_headers(@options[:headers]) unless @options[:headers].is_a?(Proc)
6
8
  end
7
9
 
8
10
  def headers
9
- Util::Headers.normalize_headers(@options[:headers])
11
+ @options[:headers]
10
12
  end
11
13
 
12
14
  def body
13
15
  return '' unless @options.has_key?(:body)
14
-
15
- if !@options[:body].include?("\0") && File.exists?(@options[:body]) && !File.directory?(@options[:body])
16
- File.read(@options[:body])
17
- else
16
+ case @options[:body]
17
+ when IO
18
+ @options[:body].read
19
+ when String
18
20
  @options[:body]
19
21
  end
20
22
  end
21
-
23
+
22
24
  def status
23
25
  @options.has_key?(:status) ? @options[:status] : 200
24
26
  end
@@ -27,5 +29,15 @@ module WebMock
27
29
  raise @options[:exception].new('Exception from WebMock') if @options.has_key?(:exception)
28
30
  end
29
31
 
32
+ def dup
33
+ dup_response = super
34
+ dup_response.options = options.dup
35
+ dup_response
36
+ end
37
+
38
+ def ==(other)
39
+ options == other.options
40
+ end
41
+
30
42
  end
31
43
  end
@@ -18,7 +18,7 @@ module WebMock
18
18
  normalized_uri = Addressable::URI.heuristic_parse(uri)
19
19
  normalized_uri.query_values = normalized_uri.query_values if normalized_uri.query_values
20
20
  normalized_uri.normalize!
21
- normalized_uri.port = normalized_uri.inferred_port unless normalized_uri.port && normalized_uri.inferred_port
21
+ normalized_uri.port = normalized_uri.inferred_port unless normalized_uri.port
22
22
  normalized_uri
23
23
  end
24
24
 
@@ -34,7 +34,7 @@ module WebMock
34
34
  uris = uris_with_scheme_and_without(uris)
35
35
  end
36
36
 
37
- if normalized_uri.path == '/' && normalized_uri.query == nil
37
+ if normalized_uri.path == '/'
38
38
  uris = uris_with_trailing_slash_and_without(uris)
39
39
  end
40
40
 
@@ -13,13 +13,13 @@ module WebMock
13
13
 
14
14
  def assert_requested(method, uri, options = {})
15
15
  expected_times_executed = options.delete(:times) || 1
16
- request = RequestProfile.new(method, uri, options[:body], options[:headers])
16
+ request = RequestProfile.new(method, uri, options)
17
17
  verifier = RequestExecutionVerifier.new(request, expected_times_executed)
18
18
  assertion_failure(verifier.failure_message) unless verifier.matches?
19
19
  end
20
20
 
21
21
  def assert_not_requested(method, uri, options = {})
22
- request = RequestProfile.new(method, uri, options[:body], options[:headers])
22
+ request = RequestProfile.new(method, uri, options)
23
23
  verifier = RequestExecutionVerifier.new(request, options.delete(:times))
24
24
  assertion_failure(verifier.negative_failure_message) unless verifier.does_not_match?
25
25
  end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'webmock_spec'
3
+ require 'ostruct'
4
+
5
+ require 'httpclient'
6
+ require 'httpclient_spec_helper'
7
+
8
+ describe "Webmock with HTTPClient" do
9
+ include HTTPClientSpecHelper
10
+
11
+ before(:each) do
12
+ HTTPClientSpecHelper.async_mode = false
13
+ end
14
+
15
+ it_should_behave_like "WebMock"
16
+
17
+ it "should yield block on response if block provided" do
18
+ stub_http_request(:get, "www.example.com").to_return(:body => "abc")
19
+ response_body = ""
20
+ http_request(:get, "http://www.example.com/") do |body|
21
+ response_body = body
22
+ end
23
+ response_body.should == "abc"
24
+ end
25
+
26
+ describe "async requests" do
27
+
28
+ before(:each) do
29
+ HTTPClientSpecHelper.async_mode = true
30
+ end
31
+
32
+ it_should_behave_like "WebMock"
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,57 @@
1
+ module HTTPClientSpecHelper
2
+ class << self
3
+ attr_accessor :async_mode
4
+ end
5
+
6
+ def http_request(method, uri, options = {}, &block)
7
+ uri = Addressable::URI.heuristic_parse(uri)
8
+ c = HTTPClient.new
9
+ c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
10
+ c.set_basic_auth(nil, uri.user, uri.password) if uri.user
11
+ params = [method, "#{uri.omit(:userinfo, :query).normalize.to_s}",
12
+ uri.query_values, options[:body], options[:headers] || {}]
13
+ if HTTPClientSpecHelper.async_mode
14
+ connection = c.request_async(*params)
15
+ connection.join
16
+ response = connection.pop
17
+ else
18
+ response = c.request(*params, &block)
19
+ end
20
+ OpenStruct.new({
21
+ :body => HTTPClientSpecHelper.async_mode ? response.content.read : response.content,
22
+ :headers => Hash[response.header.all],
23
+ :status => response.code.to_s })
24
+ end
25
+
26
+ def setup_expectations_for_real_request(options = {})
27
+ socket = mock("TCPSocket")
28
+ TCPSocket.should_receive(:new).
29
+ with(options[:host], options[:port]).at_least(:once).and_return(socket)
30
+
31
+ socket.stub!(:closed?).and_return(false)
32
+ socket.stub!(:close).and_return(true)
33
+
34
+ request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"]
35
+
36
+ if options[:port] == 443
37
+ OpenSSL::SSL::SSLSocket.should_receive(:new).
38
+ with(socket, instance_of(OpenSSL::SSL::SSLContext)).
39
+ at_least(:once).and_return(socket = mock("SSLSocket"))
40
+ socket.should_receive(:connect).at_least(:once).with()
41
+ socket.should_receive(:peer_cert).and_return(mock('peer cert', :extensions => []))
42
+ socket.should_receive(:write).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
43
+ else
44
+ socket.should_receive(:<<).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
45
+ end
46
+
47
+ socket.stub!(:sync=).with(true)
48
+
49
+ socket.should_receive(:gets).with("\n").once.and_return("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}")
50
+
51
+ socket.stub!(:eof?).and_return(true)
52
+ socket.stub!(:close).and_return(true)
53
+
54
+ socket.should_receive(:readpartial).any_number_of_times.and_raise(EOFError)
55
+ end
56
+
57
+ end
@@ -1,34 +1,25 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require 'webmock_spec'
3
3
  require 'ostruct'
4
+ require 'net_http_spec_helper'
4
5
 
5
- def http_request(method, uri, options = {})
6
- begin
7
- uri = URI.parse(uri)
8
- rescue
9
- uri = Addressable::URI.heuristic_parse(uri)
10
- end
11
- response = nil
12
- clazz = Net::HTTP.const_get("#{method.to_s.capitalize}")
13
- req = clazz.new("#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", options[:headers])
14
- req.basic_auth uri.user, uri.password if uri.user
15
- http = Net::HTTP.new(uri.host, uri.port)
16
- http.use_ssl = true if uri.scheme == "https"
17
- response = http.start {|http|
18
- http.request(req, options[:body])
19
- }
20
- OpenStruct.new({
21
- :body => response.body,
22
- :headers => response,
23
- :status => response.code })
24
- end
6
+ include NetHTTPSpecHelper
25
7
 
26
8
  describe "Webmock with Net:HTTP" do
27
-
9
+
28
10
  it_should_behave_like "WebMock"
29
-
11
+
30
12
  it "should work with block provided" do
31
- stub_http_request(:get, "www.google.com").to_return(:body => "abc"*100000)
32
- Net::HTTP.start("www.google.com") { |query| query.get("/") }.body.should == "abc"*100000
13
+ stub_http_request(:get, "www.example.com").to_return(:body => "abc"*100000)
14
+ Net::HTTP.start("www.example.com") { |query| query.get("/") }.body.should == "abc"*100000
15
+ end
16
+
17
+ it "should yield block on response" do
18
+ stub_http_request(:get, "www.example.com").to_return(:body => "abc")
19
+ response_body = ""
20
+ http_request(:get, "http://www.example.com/") do |response|
21
+ response_body = response.body
22
+ end
23
+ response_body.should == "abc"
33
24
  end
34
25
  end
@@ -0,0 +1,53 @@
1
+ module NetHTTPSpecHelper
2
+ def http_request(method, uri, options = {}, &block)
3
+ begin
4
+ uri = URI.parse(uri)
5
+ rescue
6
+ uri = Addressable::URI.heuristic_parse(uri)
7
+ end
8
+ response = nil
9
+ clazz = Net::HTTP.const_get("#{method.to_s.capitalize}")
10
+ req = clazz.new("#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", options[:headers])
11
+
12
+ req.basic_auth uri.user, uri.password if uri.user
13
+ http = Net::HTTP.new(uri.host, uri.port)
14
+ http.use_ssl = true if uri.scheme == "https"
15
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
16
+ response = http.start {|http|
17
+ http.request(req, options[:body], &block)
18
+ }
19
+ OpenStruct.new({
20
+ :body => response.body,
21
+ :headers => response,
22
+ :status => response.code })
23
+ end
24
+
25
+ # Sets several expectations that a real HTTP request makes it
26
+ # past WebMock to the socket layer. You can use this when you need to check
27
+ # that a request isn't handled by WebMock
28
+ #This solution is copied from FakeWeb project
29
+ def setup_expectations_for_real_request(options = {})
30
+ # Socket handling
31
+ if options[:port] == 443
32
+ socket = mock("SSLSocket")
33
+ OpenSSL::SSL::SSLSocket.should_receive(:===).with(socket).at_least(:once).and_return(true)
34
+ OpenSSL::SSL::SSLSocket.should_receive(:new).with(socket, instance_of(OpenSSL::SSL::SSLContext)).at_least(:once).and_return(socket)
35
+ socket.stub!(:sync_close=).and_return(true)
36
+ socket.should_receive(:connect).at_least(:once).with()
37
+ else
38
+ socket = mock("TCPSocket")
39
+ Socket.should_receive(:===).with(socket).at_least(:once).and_return(true)
40
+ end
41
+
42
+ TCPSocket.should_receive(:open).with(options[:host], options[:port]).at_least(:once).and_return(socket)
43
+ socket.stub!(:closed?).and_return(false)
44
+ socket.stub!(:close).and_return(true)
45
+
46
+ # Request/response handling
47
+ request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"]
48
+ socket.should_receive(:write).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
49
+
50
+ socket.should_receive(:sysread).once.and_return("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}")
51
+ socket.should_receive(:sysread).any_number_of_times.and_raise(EOFError)
52
+ end
53
+ end
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe RequestExecutionVerifier do
4
4
  before(:each) do
5
5
  @verifier = RequestExecutionVerifier.new
6
- @request_profile = mock(RequestProfile, :to_s => "www.google.com")
6
+ @request_profile = mock(RequestProfile, :to_s => "www.example.com")
7
7
  @verifier.request_profile = @request_profile
8
8
  end
9
9
 
@@ -13,13 +13,13 @@ describe RequestExecutionVerifier do
13
13
  it "should report failure message" do
14
14
  @verifier.times_executed = 0
15
15
  @verifier.expected_times_executed = 2
16
- @verifier.failure_message.should == "The request www.google.com was expected to execute 2 times but it executed 0 times"
16
+ @verifier.failure_message.should == "The request www.example.com was expected to execute 2 times but it executed 0 times"
17
17
  end
18
18
 
19
19
  it "should report failure message correctly when executed times is one" do
20
20
  @verifier.times_executed = 1
21
21
  @verifier.expected_times_executed = 1
22
- @verifier.failure_message.should == "The request www.google.com was expected to execute 1 time but it executed 1 time"
22
+ @verifier.failure_message.should == "The request www.example.com was expected to execute 1 time but it executed 1 time"
23
23
  end
24
24
 
25
25
  end
@@ -29,12 +29,12 @@ describe RequestExecutionVerifier do
29
29
  it "should report failure message if it executed number of times specified" do
30
30
  @verifier.times_executed = 2
31
31
  @verifier.expected_times_executed = 2
32
- @verifier.negative_failure_message.should == "The request www.google.com was not expected to execute 2 times but it executed 2 times"
32
+ @verifier.negative_failure_message.should == "The request www.example.com was not expected to execute 2 times but it executed 2 times"
33
33
  end
34
34
 
35
35
  it "should report failure message when not expected request but it executed" do
36
36
  @verifier.times_executed = 1
37
- @verifier.negative_failure_message.should == "The request www.google.com was expected to execute 0 times but it executed 1 time"
37
+ @verifier.negative_failure_message.should == "The request www.example.com was expected to execute 0 times but it executed 1 time"
38
38
  end
39
39
 
40
40
  end