wrest 0.0.7-java → 0.0.8-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,11 +13,25 @@ module Wrest::Resource #:nodoc:
13
13
  class Base
14
14
  include Wrest::Components::AttributesContainer
15
15
  include Wrest::Components::AttributesContainer::Typecaster
16
-
17
- always_has :id
16
+
17
+ always_has :id
18
18
  typecast :id => as_integer
19
19
  attr_reader :attributes
20
20
 
21
+ def ==(other)
22
+ return true if self.equal?(other)
23
+ return false unless other.class == self.class
24
+ return self.attributes == other.attributes
25
+ end
26
+
27
+ def hash
28
+ id.hash
29
+ end
30
+
31
+ def to_xml(options={})
32
+ attributes.to_xml({:root => self.class.resource_name.gsub('_', '-')}.merge(options))
33
+ end
34
+
21
35
  class << self
22
36
  def inherited(klass)
23
37
  klass.set_resource_name klass.name
@@ -29,7 +43,7 @@ module Wrest::Resource #:nodoc:
29
43
  # we often do while writing tests.
30
44
  # By default, the resource name is set to the name of the class.
31
45
  def set_resource_name(resource_name)
32
- self.class_eval "def self.resource_name; '#{resource_name}';end"
46
+ self.class_eval "def self.resource_name; '#{resource_name.underscore}';end"
33
47
  end
34
48
 
35
49
  # Allows the host url at which the resource is found to be configured
@@ -42,43 +56,44 @@ module Wrest::Resource #:nodoc:
42
56
  def set_host(host)
43
57
  self.class_eval "def self.host; '#{host}';end"
44
58
  end
45
-
59
+
46
60
  def set_default_format(format)
47
61
  self.class_eval "def self.default_format; '#{format.to_s}';end"
48
62
  end
49
-
50
- def set_redirect_handler(method_object)
51
- end
52
63
 
53
- def resource_path
54
- @resource_path ||= "/#{resource_name.underscore.pluralize}"
55
- end
56
-
57
- def resource_collection_url
58
- "#{host}#{resource_path}"
64
+ def set_redirect_handler(method_object)
59
65
  end
60
66
 
61
- def find_all
67
+ def resource_collection_name
68
+ @resource_collection_name ||= "#{resource_name.underscore.pluralize}"
62
69
  end
63
70
 
64
- def find(resource_type = [:one, :collection, :singleton], from = "")
71
+ def find_one_uri_template
72
+ @find_one_template ||= Wrest::UriTemplate.new(':host/:resource_collection_name/:id.:format')
65
73
  end
66
74
 
67
75
  def find(id)
68
- response_hash = "#{resource_collection_url}/#{id}.#{default_format}".to_uri.get.deserialise.mutate_using(
69
- Wrest::Components::Mutators.chain(
70
- :xml_mini_type_caster, :camel_to_snake_case
71
- )
72
- )
73
- resource_type = response_hash.keys.first
74
- if(resource_type.underscore.camelize == self.name)
75
- self.new(response_hash[resource_type])
76
- else
77
- response_hash
78
- end
76
+ response = find_one_uri_template.to_uri(
77
+ :host => host,
78
+ :resource_collection_name => resource_collection_name,
79
+ :id => id,
80
+ :format => default_format
81
+ ).get
82
+ self.new(response.deserialise.mutate_using(
83
+ Wrest::Components::Mutators.chain(:xml_mini_type_caster, :camel_to_snake_case)
84
+ ).shift.last)
79
85
  end
80
86
 
81
- def objectify(hash)
87
+ def create(attributes = {})
88
+ response = Wrest::UriTemplate.new(':host/:resource_collection_name.:format').to_uri(
89
+ :host => host,
90
+ :resource_collection_name => resource_collection_name,
91
+ :format => default_format
92
+ ).post(self.new(attributes).to_xml, 'Content-Type' => "application/#{default_format}")
93
+
94
+ self.new(response.deserialise.mutate_using(
95
+ Wrest::Components::Mutators.chain(:xml_mini_type_caster, :camel_to_snake_case)
96
+ ).shift.last)
82
97
  end
83
98
  end
84
99
  end
data/lib/wrest/uri.rb CHANGED
@@ -11,10 +11,44 @@ module Wrest #:nodoc:
11
11
  # Wrest::Uri provides a simple api for
12
12
  # REST calls. String#to_uri is a convenience
13
13
  # method to build a Wrest::Uri from a string url.
14
+ # Note that a Wrest::Uri is immutable.
15
+ #
16
+ # Basic HTTP Authentication is supported.
17
+ # Example:
18
+ # "http://kaiwren:fupuppies@coathangers.com/portal/1".to_uri
19
+ # "http://coathangers.com/portal/1".to_uri(:username => 'kaiwren', :password => 'fupuppies')
20
+ #
21
+ # The second form is preferred as it can handle passwords with special characters like ^ and @
22
+ #
23
+ # You can find examples that use real APIs (like delicious) under the wrest/examples directory.
14
24
  class Uri
15
- attr_reader :uri
16
- def initialize(uri_string)
25
+ attr_reader :uri, :username, :password
26
+ def initialize(uri_string, options = {})
27
+ @options = options
28
+ @uri_string = uri_string.clone
17
29
  @uri = URI.parse(uri_string)
30
+ @options = options
31
+ @username = (@options[:username] ||= @uri.user)
32
+ @password = (@options[:password] ||= @uri.password)
33
+ end
34
+
35
+ # Build a new Wrest::Uri by appending _path_ to
36
+ # the current uri. If the original Wrest::Uri
37
+ # has a username and password, that will be
38
+ # copied to the new Wrest::Uri as well.
39
+ #
40
+ # Example:
41
+ # uri = "https://localhost:3000/v1".to_uri
42
+ # uri['/oogas/1'].get
43
+ #
44
+ # To change the username and password on the new
45
+ # instance, simply pass them as an options map.
46
+ #
47
+ # Example:
48
+ # uri = "https://localhost:3000/v1".to_uri(:username => 'foo', :password => 'bar')
49
+ # uri['/oogas/1', {:username => 'meh', :password => 'baz'}].get
50
+ def [](path, options = nil)
51
+ Uri.new(@uri_string+path, options || @options)
18
52
  end
19
53
 
20
54
  def eql?(other)
@@ -23,56 +57,74 @@ module Wrest #:nodoc:
23
57
 
24
58
  def ==(other)
25
59
  return false if other.class != self.class
26
- return other.uri == self.uri
60
+ return other.uri == self.uri && self.username == other.username && self.password == other.password
27
61
  end
28
62
 
29
63
  def hash
30
- self.uri.hash + 20090423
64
+ @uri.hash + @username.hash + @password.hash + 20090423
31
65
  end
32
66
 
33
- # Make a HTTP get request to this URI.
34
- # Remember to escape the parameter strings using URI.escape
67
+ # Make a GET request to this URI. This is a convenience API
68
+ # that creates a Wrest::Http::Get, executes it and returns a Wrest::Http::Response.
69
+ #
70
+ # Remember to escape all parameter strings if necessary, using URI.escape
35
71
  def get(parameters = {}, headers = {})
36
- do_request 'get', parameters.empty? ? @uri.request_uri : "#{@uri.request_uri}?#{parameters.to_query}", headers.stringify_keys
72
+ Http::Get.new(self, parameters, headers, @options).invoke
37
73
  end
38
74
 
39
- def put(body = '', headers = {})
40
- do_request 'put', @uri.request_uri, body.to_s, headers.stringify_keys
75
+ # Make a PUT request to this URI. This is a convenience API
76
+ # that creates a Wrest::Http::Put, executes it and returns a Wrest::Http::Response.
77
+ #
78
+ # Remember to escape all parameter strings if necessary, using URI.escape
79
+ def put(body = '', headers = {}, parameters = {})
80
+ Http::Put.new(self, body.to_s, headers, parameters, @options).invoke
41
81
  end
42
82
 
43
- def post(body = '', headers = {})
44
- do_request 'post', @uri.request_uri, body.to_s, headers.stringify_keys
83
+ # Makes a POST request to this URI. This is a convenience API
84
+ # that creates a Wrest::Http::Post, executes it and returns a Wrest::Http::Response.
85
+ #
86
+ # Remember to escape all parameter strings if necessary, using URI.escape
87
+ def post(body = '', headers = {}, parameters = {})
88
+ Http::Post.new(self, body.to_s, headers, parameters, @options).invoke
45
89
  end
46
90
 
91
+ # Makes a DELETE request to this URI. This is a convenience API
92
+ # that creates a Wrest::Http::Delete, executes it and returns a Wrest::Http::Response.
93
+ #
94
+ # Remember to escape all parameter strings if necessary, using URI.escape
47
95
  def delete(parameters = {}, headers = {})
48
- do_request 'delete', parameters.empty? ? @uri.request_uri : "#{@uri.request_uri}?#{parameters.to_query}", headers.stringify_keys
96
+ Http::Delete.new(self, parameters, headers, @options).invoke
49
97
  end
50
98
 
99
+ # Makes an OPTIONS request to this URI. This is a convenience API
100
+ # that creates a Wrest::Http::Options, executes it and returns the Wrest::Http::Response.
51
101
  def options
52
- do_request 'options', @uri.request_uri
102
+ Http::Options.new(self, @options).invoke
53
103
  end
54
-
55
- def do_request(method, url, *args)
56
- response = nil
57
-
58
- Wrest.logger.info "--> (#{method}) #{@uri.scheme}://#{@uri.host}:#{@uri.port}#{url}"
59
- time = Benchmark.realtime { response = Wrest::Response.new(http.send(method, url, *args)) }
60
- Wrest.logger.info "--> %d %s (%d %.2fs)" % [response.code, response.message, response.body ? response.body.length : 0, time]
61
104
 
62
- response
63
- end
64
-
65
105
  def https?
66
106
  @uri.is_a?(URI::HTTPS)
67
107
  end
68
-
69
- def http
70
- http = Net::HTTP.new(@uri.host, @uri.port)
71
- if https?
72
- http.use_ssl = true
73
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
74
- end
75
- http
108
+
109
+ # Provides the full path of a request.
110
+ # For example, for
111
+ # http://localhost:3000/demons/1/chi?sort=true
112
+ # this would return
113
+ # /demons/1/chi?sort=true
114
+ def full_path
115
+ uri.request_uri
116
+ end
117
+
118
+ def protocol
119
+ uri.scheme
120
+ end
121
+
122
+ def host
123
+ uri.host
124
+ end
125
+
126
+ def port
127
+ uri.port
76
128
  end
77
129
  end
78
130
  end
@@ -19,9 +19,26 @@ module Wrest
19
19
  # the corressponding values.
20
20
  #
21
21
  # Example:
22
- # template = UriTemplate.new("http://localhost:3000/:resource/:id.:format")
22
+ # template = UriTemplate.new("http://coathangers.com/:resource/:id.:format")
23
23
  # template.to_uri(:resource => 'shen_coins', :id => 5, :format => :json)
24
24
  # => #<Wrest::Uri:0x1225514 @uri=#<URI::HTTP:0x9127d8 URL:http://localhost:3000/shen_coins/5.json>>
25
+ #
26
+ # This feature can also be used to handle HTTP authentication where the username
27
+ # and password needs changing at runtime. However, this approach _will_ fail if
28
+ # the password contains characters like ^ and @.
29
+ #
30
+ # Note that beacuse because both HTTP Auth and UriTemplate
31
+ # use ':' as a delimiter, the pattern does look slightly weird, but it still works.
32
+ #
33
+ # Example:
34
+ # template = UriTemplate.new("http://:username::password@coathangers.com/:resource/:id.:format")
35
+ # template.to_uri(
36
+ # :user => 'kaiwren',
37
+ # :password => 'fupuppies',
38
+ # :resource => 'portal',
39
+ # :id => '1'
40
+ # )
41
+ # => #<Wrest::Uri:0x18e0bec @uri=#<URI::HTTP:0x18e09a8 URL:http://kaiwren:fupuppies@coathangers.com/portal/1>>
25
42
  def to_uri(options = {})
26
43
  options.inject(uri_pattern.clone) do |uri_string, tuple|
27
44
  key, value = tuple
data/lib/wrest/version.rb CHANGED
@@ -12,7 +12,7 @@ module Wrest
12
12
  unless defined? MAJOR
13
13
  MAJOR = 0
14
14
  MINOR = 0
15
- TINY = 7
15
+ TINY = 8
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY].join('.')
18
18
 
@@ -179,6 +179,17 @@ module Wrest::Components
179
179
  @li_piao.id = 6
180
180
  @li_piao.id.should == 6
181
181
  end
182
+
183
+ it "should provide getter and query methods to instance which has corresponding attribute" do
184
+ zotoh_zhaan = HumanBeing.new(:species => "Delvian")
185
+ zotoh_zhaan.species.should == "Delvian"
186
+ zotoh_zhaan.species?.should be_true
187
+ zotoh_zhaan.species = "Human"
188
+ lambda{@li_piao.species}.should raise_error(NoMethodError)
189
+ lambda{@li_piao.species?}.should raise_error(NoMethodError)
190
+ @li_piao.should_not respond_to(:species=)
191
+ @li_piao.methods.grep(/:species=/).should be_empty
192
+ end
182
193
  end
183
194
  end
184
195
  end
@@ -13,4 +13,13 @@ describe String, 'conversions' do
13
13
  it "should know how to convert a string to a Wrest::Uri" do
14
14
  'http://localhost:3000'.to_uri.should == Wrest::Uri.new('http://localhost:3000')
15
15
  end
16
+
17
+ it "should accept username and password as options" do
18
+ uri = 'http://localhost:3000'.to_uri(
19
+ :username => 'ooga',
20
+ :password => 'booga'
21
+ )
22
+ uri.username.should == 'ooga'
23
+ uri.password.should == 'booga'
24
+ end
16
25
  end
@@ -0,0 +1,22 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ require File.dirname(__FILE__) + '/../../spec_helper'
11
+
12
+ describe Wrest::Http::Request do
13
+ it "should convert all symbols in header keys to strings" do
14
+ Wrest::Http::Request.new(
15
+ 'http://localhost/foo'.to_uri, Net::HTTP::Get, {},
16
+ nil, 'Content-Type' => 'application/xml', :per_page => '10'
17
+ ).headers.should == {
18
+ 'Content-Type' => 'application/xml',
19
+ 'per_page' => '10'
20
+ }
21
+ end
22
+ end
@@ -1,18 +1,18 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
3
  module Wrest
4
- describe Response do
4
+ describe Http::Response do
5
5
  it "should know how to delegate to a translator" do
6
6
  http_response = mock('response')
7
7
  Components::Translators::Xml.should_receive(:deserialise).with(http_response)
8
- Response.new(http_response).deserialise_using(Components::Translators::Xml)
8
+ Http::Response.new(http_response).deserialise_using(Components::Translators::Xml)
9
9
  end
10
10
 
11
11
  it "should know how to load a translator based on content type" do
12
12
  http_response = mock('response')
13
13
  http_response.should_receive(:content_type).and_return('application/xml')
14
14
 
15
- response = Response.new(http_response)
15
+ response = Http::Response.new(http_response)
16
16
  response.should_receive(:deserialise_using).with(Components::Translators::Xml)
17
17
 
18
18
  response.deserialise
@@ -5,11 +5,12 @@ class Glassware < Wrest::Resource::Base
5
5
  end
6
6
 
7
7
  class BottledUniverse < Glassware
8
- set_host "http://localhost:3001"
8
+ set_host "http://localhost:3001"
9
+ set_default_format :xml
9
10
  end
10
11
 
11
12
  module Wrest
12
- describe Resource::Base do
13
+ describe Wrest::Resource::Base do
13
14
  it "should not affect other classes when setting up its macros" do
14
15
  Class.should_not respond_to(:host=)
15
16
  Object.should_not respond_to(:host=)
@@ -23,21 +24,80 @@ module Wrest
23
24
  before(:each) do
24
25
  @BottledUniverse = Class.new(Resource::Base)
25
26
  @BottledUniverse.class_eval do
26
- set_resource_name 'BottledUniverse'
27
+ set_resource_name 'BottledUniverse'
28
+ end
29
+ end
30
+
31
+ describe 'equality' do
32
+ it "should be equal if it is the same instance" do
33
+ universe = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
34
+ (universe == universe).should be_true
35
+ end
36
+
37
+ it "should be equal if it has the same state" do
38
+ (
39
+ @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1) == @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
40
+ ).should be_true
41
+ end
42
+
43
+ it "should not be equal to nil" do
44
+ (@BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1) == nil).should be_false
45
+ end
46
+
47
+ it "should not be equal if it is not the same class" do
48
+ (
49
+ @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1) == Glassware.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
50
+ ).should be_false
51
+ end
52
+
53
+ it "should not be equal if it is has a different state" do
54
+ (
55
+ @BottledUniverse.new(:universe_id=>3, :name=>"Wooz", :id=>1) == @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
56
+ ).should be_false
57
+ end
58
+
59
+ it "should be symmetric" do
60
+ universe_one = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
61
+ universe_two = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
62
+ (universe_one == universe_one).should be_true
63
+ (universe_two == universe_two).should be_true
64
+ end
65
+
66
+ it "should be transitive" do
67
+ universe_one = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
68
+ universe_two = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
69
+ universe_three = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
70
+ (universe_one == universe_two).should be_true
71
+ (universe_two == universe_three).should be_true
72
+ (universe_one == universe_three).should be_true
73
+ end
74
+
75
+ it "should ensure that the hashcode is a fixnum" do
76
+ @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1).hash.should be_kind_of(Fixnum)
77
+ end
78
+
79
+ it "should ensure that instances with the same ids have the same hashcode" do
80
+ universe_one = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
81
+ universe_two = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
82
+ universe_one.hash.should == universe_two.hash
83
+ end
84
+
85
+ it "should ensure that instances with different ids have the different hashcodes" do
86
+ universe_one = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
87
+ universe_two = @BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>2)
88
+ universe_one.hash.should_not == universe_two.hash
27
89
  end
28
90
  end
29
91
 
30
92
  it "should know its name as a resource by default" do
31
- BottledUniverse.resource_name.should == 'BottledUniverse'
93
+ BottledUniverse.resource_name.should == 'bottled_universe'
32
94
  end
33
95
 
34
96
  it "should allow its name as a resource to be configured for anonymous classes" do
35
- @BottledUniverse.resource_name.should == 'BottledUniverse'
97
+ @BottledUniverse.resource_name.should == 'bottled_universe'
36
98
  end
37
99
 
38
100
  it "should know how to create an instance using deserialised attributes" do
39
- # Json => {"lead_bottle"=>{"name"=>"Wooz", "id"=>1, "universe_id"=>nil}}
40
- # Xml => {"lead-bottle"=>[{"name"=>["Wooz"], "universe-id"=>[{"type"=>"integer", "nil"=>"true"}], "id"=>[{"type"=>"integer", "content"=>"1"}]}]}
41
101
  universe = @BottledUniverse.new "name"=>"Wooz", "id"=>'1', "universe_id"=>nil, 'owner_id'=>nil
42
102
  universe.name.should == "Wooz"
43
103
  universe.owner_id.should be_nil
@@ -69,8 +129,48 @@ module Wrest
69
129
  @BottledUniverse.host.should == "http://localhost:3000"
70
130
  end
71
131
 
72
- it "should know its resource path" do
73
- Glassware.resource_path.should == '/glasswares'
132
+ it "should know its resource collection name" do
133
+ Glassware.resource_collection_name.should == 'glasswares'
134
+ end
135
+
136
+ it "should know its uri template for find one" do
137
+ Glassware.find_one_uri_template.to_uri(
138
+ :host => 'http://localhost:3000',
139
+ :resource_collection_name => 'glasswares',
140
+ :id => 1,
141
+ :format => 'json'
142
+ ).should == 'http://localhost:3000/glasswares/1.json'.to_uri
143
+ end
144
+
145
+ it "should know how to serialise itself to xml" do
146
+ BottledUniverse.new(:name => 'Foo').to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bottled-universe>\n <name>Foo</name>\n</bottled-universe>\n"
147
+ end
148
+
149
+ describe 'finders' do
150
+ # Json =>
151
+ # body => {"lead_bottle": {"name": "Wooz", "id": 1, "universe_id": null}}
152
+ # hash => {"lead_bottle"=>{"name"=>"Wooz", "id"=>1, "universe_id"=>nil}}
153
+ # Xml =>
154
+ # body =>
155
+ # <?xml version="1.0" encoding="UTF-8"?>
156
+ # <lead-bottle>
157
+ # <id type="integer">1</id>
158
+ # <name>Wooz</name>
159
+ # <universe-id type="integer" nil="true"></universe-id>
160
+ # </lead-bottle>
161
+ # hash =>
162
+ # {"lead-bottle"=>{"name"=>{"__content__"=>"Wooz"}, "universe-id"=>{"type"=>"integer", "nil"=>"true"}, "id"=>{"__content__"=>"1", "type"=>"integer"}}}
163
+ # typecast =>
164
+ # {"lead_bottle"=>{"name"=>"Wooz", "id"=>1, "universe_id"=>nil}}
165
+ it "should know how to find a resource by id" do
166
+ uri = 'http://localhost:3001/bottled_universe/1.xml'.to_uri
167
+ Wrest::Uri.should_receive(:new).with('http://localhost:3001/bottled_universes/1.xml', {}).and_return(uri)
168
+ response = mock(Wrest::Http::Response)
169
+ uri.should_receive(:get).with(no_args).and_return(response)
170
+ response.should_receive(:deserialise).and_return({"bottled-universe"=>{"name"=>{"__content__"=>"Wooz"}, "universe-id"=>{"type"=>"integer", "nil"=>"true"}, "id"=>{"__content__"=>"1", "type"=>"integer"}}})
171
+
172
+ BottledUniverse.find(1).should == BottledUniverse.new(:universe_id=>nil, :name=>"Wooz", :id=>1)
173
+ end
74
174
  end
75
175
  end
76
176
 
@@ -80,8 +180,23 @@ module Wrest
80
180
  BottledUniverse.host.should == "http://localhost:3001"
81
181
  end
82
182
 
83
- it "should know its resource path when it is a subclass of a subclass" do
84
- BottledUniverse.resource_path.should == '/bottled_universes'
183
+ it "should know its resource collection name when it is a subclass of a subclass" do
184
+ BottledUniverse.resource_collection_name.should == 'bottled_universes'
185
+ end
186
+
187
+
188
+ it "should know how to create a new resource" do
189
+ uri = mock(Uri)
190
+ mock_http_response = mock(Net::HTTPResponse)
191
+ mock_http_response.stub!(:content_type).and_return('application/xml')
192
+ mock_http_response.stub!(:body).and_return("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bottled-universe>\n <name>Woot</name>\n <id>1</id>\n </bottled-universe>\n")
193
+
194
+ Uri.should_receive(:new).with("http://localhost:3001/bottled_universes.xml", {}).and_return(uri)
195
+ uri.should_receive(:post).with(
196
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<bottled-universe>\n <name>Woot</name>\n</bottled-universe>\n",
197
+ 'Content-Type' => 'application/xml'
198
+ ).and_return(Wrest::Http::Response.new(mock_http_response))
199
+ ware = BottledUniverse.create(:name => 'Woot')
85
200
  end
86
201
  end
87
202