actionwebservice 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGELOG +21 -0
  2. data/README +50 -6
  3. data/Rakefile +9 -9
  4. data/TODO +6 -6
  5. data/lib/action_web_service.rb +4 -3
  6. data/lib/action_web_service/api.rb +248 -1
  7. data/lib/action_web_service/casting.rb +111 -0
  8. data/lib/action_web_service/client/soap_client.rb +17 -33
  9. data/lib/action_web_service/client/xmlrpc_client.rb +10 -34
  10. data/lib/action_web_service/container/delegated_container.rb +1 -1
  11. data/lib/action_web_service/dispatcher/abstract.rb +52 -72
  12. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +71 -55
  13. data/lib/action_web_service/protocol/abstract.rb +82 -3
  14. data/lib/action_web_service/protocol/discovery.rb +2 -2
  15. data/lib/action_web_service/protocol/soap_protocol.rb +95 -22
  16. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +197 -0
  17. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +56 -24
  18. data/lib/action_web_service/scaffolding.rb +237 -0
  19. data/lib/action_web_service/struct.rb +17 -4
  20. data/lib/action_web_service/support/signature_types.rb +194 -0
  21. data/lib/action_web_service/templates/scaffolds/layout.rhtml +65 -0
  22. data/lib/action_web_service/templates/scaffolds/methods.rhtml +6 -0
  23. data/lib/action_web_service/templates/scaffolds/parameters.rhtml +28 -0
  24. data/lib/action_web_service/templates/scaffolds/result.rhtml +30 -0
  25. data/lib/action_web_service/test_invoke.rb +23 -42
  26. data/test/abstract_dispatcher.rb +102 -48
  27. data/test/abstract_unit.rb +1 -1
  28. data/test/api_test.rb +40 -7
  29. data/test/casting_test.rb +82 -0
  30. data/test/client_soap_test.rb +3 -0
  31. data/test/client_xmlrpc_test.rb +5 -1
  32. data/test/dispatcher_action_controller_soap_test.rb +9 -12
  33. data/test/dispatcher_action_controller_xmlrpc_test.rb +1 -11
  34. data/test/run +1 -0
  35. data/test/scaffolded_controller_test.rb +67 -0
  36. data/test/struct_test.rb +33 -21
  37. data/test/test_invoke_test.rb +1 -1
  38. metadata +18 -31
  39. data/lib/action_web_service/api/base.rb +0 -135
  40. data/lib/action_web_service/vendor/ws.rb +0 -4
  41. data/lib/action_web_service/vendor/ws/common.rb +0 -8
  42. data/lib/action_web_service/vendor/ws/encoding.rb +0 -3
  43. data/lib/action_web_service/vendor/ws/encoding/abstract.rb +0 -26
  44. data/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb +0 -90
  45. data/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb +0 -53
  46. data/lib/action_web_service/vendor/ws/marshaling.rb +0 -3
  47. data/lib/action_web_service/vendor/ws/marshaling/abstract.rb +0 -17
  48. data/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb +0 -277
  49. data/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb +0 -116
  50. data/lib/action_web_service/vendor/ws/types.rb +0 -165
  51. data/test/ws/abstract_encoding.rb +0 -68
  52. data/test/ws/abstract_unit.rb +0 -13
  53. data/test/ws/gencov +0 -3
  54. data/test/ws/run +0 -5
  55. data/test/ws/soap_marshaling_test.rb +0 -91
  56. data/test/ws/soap_rpc_encoding_test.rb +0 -47
  57. data/test/ws/types_test.rb +0 -43
  58. data/test/ws/xmlrpc_encoding_test.rb +0 -34
@@ -0,0 +1,65 @@
1
+ <html>
2
+ <head>
3
+ <title><%= @scaffold_class.wsdl_service_name %> Web Service</title>
4
+ <style>
5
+ body { background-color: #fff; color: #333; }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a { color: #000; }
20
+ a:visited { color: #666; }
21
+ a:hover { color: #fff; background-color:#000; }
22
+
23
+ .fieldWithErrors {
24
+ padding: 2px;
25
+ background-color: red;
26
+ display: table;
27
+ }
28
+
29
+ #ErrorExplanation {
30
+ width: 400px;
31
+ border: 2px solid #red;
32
+ padding: 7px;
33
+ padding-bottom: 12px;
34
+ margin-bottom: 20px;
35
+ background-color: #f0f0f0;
36
+ }
37
+
38
+ #ErrorExplanation h2 {
39
+ text-align: left;
40
+ font-weight: bold;
41
+ padding: 5px 5px 5px 15px;
42
+ font-size: 12px;
43
+ margin: -7px;
44
+ background-color: #c00;
45
+ color: #fff;
46
+ }
47
+
48
+ #ErrorExplanation p {
49
+ color: #333;
50
+ margin-bottom: 0;
51
+ padding: 5px;
52
+ }
53
+
54
+ #ErrorExplanation ul li {
55
+ font-size: 12px;
56
+ list-style: square;
57
+ }
58
+ </style>
59
+ </head>
60
+ <body>
61
+
62
+ <%= @content_for_layout %>
63
+
64
+ </body>
65
+ </html>
@@ -0,0 +1,6 @@
1
+ <% @scaffold_container.services.each do |service| %>
2
+
3
+ <h4>API Methods for <%= service %></h4>
4
+ <%= service_method_list(service) %>
5
+
6
+ <% end %>
@@ -0,0 +1,28 @@
1
+ <h4>Method Invocation Details for <em><%= @scaffold_service %>#<%= @scaffold_method.public_name %></em></h4>
2
+
3
+ <%= form_tag :action => @scaffold_action_name + '_submit' %>
4
+ <%= hidden_field_tag "service", @scaffold_service.name %>
5
+ <%= hidden_field_tag "method", @scaffold_method.public_name %>
6
+
7
+ <p>
8
+ <label for="protocol">Protocol:</label><br />
9
+ <%= select_tag 'protocol', options_for_select([['SOAP', 'soap'], ['XML-RPC', 'xmlrpc']], @params['protocol']) %>
10
+ </p>
11
+
12
+ <% if @scaffold_method.expects %>
13
+
14
+ <strong>Method Parameters:</strong><br />
15
+ <% @scaffold_method.expects.each do |type| %>
16
+ <p>
17
+ <label for="method_params[]"><%= type.name.to_s.camelize %></label><br />
18
+ <%= method_parameter_input_fields(@scaffold_method, type) %>
19
+ </p>
20
+ <% end %>
21
+
22
+ <% end %>
23
+
24
+ <%= submit_tag "Invoke" %>
25
+
26
+ <p>
27
+ <%= link_to "Back", :action => @scaffold_action_name %>
28
+ </p>
@@ -0,0 +1,30 @@
1
+ <h4>Method Invocation Result for <em><%= @scaffold_service %>#<%= @scaffold_method.public_name %></em></h4>
2
+
3
+ <p>
4
+ Invocation took <tt><%= '%f' % @method_elapsed %></tt> seconds
5
+ </p>
6
+
7
+ <p>
8
+ <strong>Return Value:</strong><br />
9
+ <pre>
10
+ <%= h @method_return_value.inspect %>
11
+ </pre>
12
+ </p>
13
+
14
+ <p>
15
+ <strong>Request XML:</strong><br />
16
+ <pre>
17
+ <%= h @method_request_xml %>
18
+ </pre>
19
+ </p>
20
+
21
+ <p>
22
+ <strong>Response XML:</strong><br />
23
+ <pre>
24
+ <%= h @method_response_xml %>
25
+ </pre>
26
+ </p>
27
+
28
+ <p>
29
+ <%= link_to "Back", :action => @scaffold_action_name + '_method_params', :method => @scaffold_method.public_name, :service => @scaffold_service.name %>
30
+ </p>
@@ -21,7 +21,7 @@ module Test # :nodoc:
21
21
 
22
22
  # invoke the specified layered API method on the correct service
23
23
  def invoke_layered(service_name, method_name, *args)
24
- if protocol == :soap
24
+ if protocol.is_a?(ActionWebService::Protocol::Soap::SoapProtocol)
25
25
  raise "SOAP protocol support for :layered dispatching mode is not available"
26
26
  end
27
27
  prepare_request('api', service_name, method_name, *args)
@@ -37,10 +37,10 @@ module Test # :nodoc:
37
37
  @request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
38
38
  @request.env['RAW_POST_DATA'] = encode_rpc_call(service_name, api_method_name, *args)
39
39
  case protocol
40
- when :soap
40
+ when ActionWebService::Protocol::Soap::SoapProtocol
41
41
  soap_action = "/#{@controller.controller_name}/#{service_name}/#{public_method_name(service_name, api_method_name)}"
42
42
  @request.env['HTTP_SOAPACTION'] = soap_action
43
- when :xmlrpc
43
+ when ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
44
44
  @request.env.delete('HTTP_SOAPACTION')
45
45
  end
46
46
  end
@@ -52,28 +52,16 @@ module Test # :nodoc:
52
52
  when :delegated, :layered
53
53
  api = @controller.web_service_object(service_name.to_sym).class.web_service_api
54
54
  end
55
- info = api.api_methods[api_method_name.to_sym]
56
- ((info[:expects] || []) + (info[:returns] || [])).each do |spec|
57
- marshaler.register_type spec
58
- end
59
- expects = info[:expects]
60
- args = args.dup
61
- (0..(args.length-1)).each do |i|
62
- type_binding = marshaler.register_type(expects ? expects[i] : args[i].class)
63
- info = WS::ParamInfo.create(expects ? expects[i] : args[i].class, type_binding, i)
64
- args[i] = marshaler.marshal(WS::Param.new(args[i], info))
65
- end
66
- encoder.encode_rpc_call(public_method_name(service_name, api_method_name), args)
55
+ protocol.register_api(api)
56
+ method = api.api_methods[api_method_name.to_sym]
57
+ protocol.encode_request(public_method_name(service_name, api_method_name), args.dup, method.expects)
67
58
  end
68
59
 
69
60
  def decode_rpc_response
70
- public_method_name, return_value = encoder.decode_rpc_response(@response.body)
71
- result = marshaler.unmarshal(return_value).value
72
- unless @return_exceptions
73
- exception = is_exception?(result)
74
- raise exception if exception
75
- end
76
- result
61
+ public_method_name, return_value = protocol.decode_response(@response.body)
62
+ exception = is_exception?(return_value)
63
+ raise exception if exception
64
+ return_value
77
65
  end
78
66
 
79
67
  def public_method_name(service_name, api_method_name)
@@ -95,33 +83,26 @@ module Test # :nodoc:
95
83
  end
96
84
 
97
85
  def protocol
98
- @protocol ||= :soap
99
- end
100
-
101
- def marshaler
102
- case protocol
103
- when :soap
104
- @soap_marshaler ||= WS::Marshaling::SoapMarshaler.new 'urn:ActionWebService'
105
- when :xmlrpc
106
- @xmlrpc_marshaler ||= WS::Marshaling::XmlRpcMarshaler.new
107
- end
108
- end
109
-
110
- def encoder
111
- case protocol
112
- when :soap
113
- @soap_encoder ||= WS::Encoding::SoapRpcEncoding.new 'urn:ActionWebService'
114
- when :xmlrpc
115
- @xmlrpc_encoder ||= WS::Encoding::XmlRpcEncoding.new
86
+ if @protocol.nil?
87
+ @protocol ||= ActionWebService::Protocol::Soap::SoapProtocol.new
88
+ else
89
+ case @protocol
90
+ when :xmlrpc
91
+ @protocol = ActionWebService::Protocol::XmlRpc::XmlRpcProtocol.new
92
+ when :soap
93
+ @protocol = ActionWebService::Protocol::Soap::SoapProtocol.new
94
+ else
95
+ @protocol
96
+ end
116
97
  end
117
98
  end
118
99
 
119
100
  def is_exception?(obj)
120
101
  case protocol
121
- when :soap
102
+ when :soap, ActionWebService::Protocol::Soap::SoapProtocol
122
103
  (obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \
123
104
  obj.detail.cause.is_a?(Exception)) ? obj.detail.cause : nil
124
- when :xmlrpc
105
+ when :xmlrpc, ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
125
106
  obj.is_a?(XMLRPC::FaultException) ? obj : nil
126
107
  end
127
108
  end
@@ -1,4 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/abstract_unit'
2
+ require 'stringio'
3
+
4
+ class ActionController::Base; def rescue_action(e) raise e end; end
2
5
 
3
6
  module DispatcherTest
4
7
  class Node < ActiveRecord::Base
@@ -29,6 +32,10 @@ module DispatcherTest
29
32
  class Person < ActionWebService::Struct
30
33
  member :id, :int
31
34
  member :name, :string
35
+
36
+ def ==(other)
37
+ self.id == other.id && self.name == other.name
38
+ end
32
39
  end
33
40
 
34
41
  class API < ActionWebService::API::Base
@@ -44,7 +51,9 @@ module DispatcherTest
44
51
  api_method :before_filtered
45
52
  api_method :after_filtered, :returns => [[:int]]
46
53
  api_method :struct_return, :returns => [[Node]]
54
+ api_method :struct_pass, :expects => [{:person => Person}]
47
55
  api_method :base_struct_return, :returns => [[Person]]
56
+ api_method :hash_struct_return, :returns => [[Person]]
48
57
  api_method :thrower
49
58
  api_method :void
50
59
  end
@@ -148,6 +157,7 @@ module DispatcherTest
148
157
  attr :after_filter_called
149
158
  attr :after_filter_target_called
150
159
  attr :void_called
160
+ attr :struct_pass_value
151
161
 
152
162
  def initialize
153
163
  @before_filter_called = false
@@ -155,6 +165,7 @@ module DispatcherTest
155
165
  @after_filter_called = false
156
166
  @after_filter_target_called = false
157
167
  @void_called = false
168
+ @struct_pass_value = false
158
169
  end
159
170
 
160
171
  def add
@@ -184,11 +195,21 @@ module DispatcherTest
184
195
  [n1, n2]
185
196
  end
186
197
 
198
+ def struct_pass(person)
199
+ @struct_pass_value = person
200
+ end
201
+
187
202
  def base_struct_return
188
203
  p1 = Person.new('id' => 1, 'name' => 'person1')
189
204
  p2 = Person.new('id' => 2, 'name' => 'person2')
190
205
  [p1, p2]
191
206
  end
207
+
208
+ def hash_struct_return
209
+ p1 = { :id => '1', 'name' => 'test' }
210
+ p2 = { 'id' => '2', :name => 'person2' }
211
+ [p1, p2]
212
+ end
192
213
 
193
214
  def void
194
215
  @void_called = @method_params
@@ -221,22 +242,11 @@ module DispatcherCommonTests
221
242
  assert_equal(50, do_method_call(@direct_controller, 'Add2', 25, 25))
222
243
  assert_equal(50, @direct_controller.added2)
223
244
  assert(@direct_controller.void_called == false)
224
- case @encoder
225
- when WS::Encoding::SoapRpcEncoding
226
- assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?)
227
- when WS::Encoding::XmlRpcEncoding
228
- assert(do_method_call(@direct_controller, 'Void', 3, 4, 5) == true)
229
- end
245
+ assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?)
230
246
  assert(@direct_controller.void_called == [])
231
247
  result = do_method_call(@direct_controller, 'BaseStructReturn')
232
- case @encoder
233
- when WS::Encoding::SoapRpcEncoding
234
- assert(result[0].is_a?(DispatcherTest::Person))
235
- assert(result[1].is_a?(DispatcherTest::Person))
236
- when WS::Encoding::XmlRpcEncoding
237
- assert(result[0].is_a?(Hash))
238
- assert(result[1].is_a?(Hash))
239
- end
248
+ assert(result[0].is_a?(DispatcherTest::Person))
249
+ assert(result[1].is_a?(DispatcherTest::Person))
240
250
  end
241
251
 
242
252
  def test_direct_entrypoint
@@ -275,12 +285,7 @@ module DispatcherCommonTests
275
285
  assert(is_exception?(result))
276
286
  assert_match(/NonExistentMethod/, exception_message(result))
277
287
  assert(service.void_called == false)
278
- case @encoder
279
- when WS::Encoding::SoapRpcEncoding
280
- assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?)
281
- when WS::Encoding::XmlRpcEncoding
282
- assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5) == true)
283
- end
288
+ assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?)
284
289
  assert(service.void_called == [])
285
290
  end
286
291
 
@@ -288,7 +293,8 @@ module DispatcherCommonTests
288
293
  [@direct_controller, @delegated_controller].each do |controller|
289
294
  controller.class.web_service_exception_reporting = true
290
295
  send_garbage_request = lambda do
291
- request = create_ap_request(controller, 'invalid request body', 'xxx')
296
+ service_name = service_name(controller)
297
+ request = @protocol.encode_action_pack_request(service_name, 'broken, method, name!', 'broken request body', :request_class => ActionController::TestRequest)
292
298
  response = ActionController::TestResponse.new
293
299
  controller.process(request, response)
294
300
  # puts response.body
@@ -313,21 +319,53 @@ module DispatcherCommonTests
313
319
  def test_ar_struct_return
314
320
  [@direct_controller, @delegated_controller].each do |controller|
315
321
  result = do_method_call(controller, 'StructReturn')
316
- case @encoder
317
- when WS::Encoding::SoapRpcEncoding
318
- assert(result[0].is_a?(DispatcherTest::Node))
319
- assert(result[1].is_a?(DispatcherTest::Node))
320
- assert_equal('node1', result[0].name)
321
- assert_equal('node2', result[1].name)
322
- when WS::Encoding::XmlRpcEncoding
323
- assert(result[0].is_a?(Hash))
324
- assert(result[1].is_a?(Hash))
325
- assert_equal('node1', result[0]['name'])
326
- assert_equal('node2', result[1]['name'])
327
- end
322
+ assert(result[0].is_a?(DispatcherTest::Node))
323
+ assert(result[1].is_a?(DispatcherTest::Node))
324
+ assert_equal('node1', result[0].name)
325
+ assert_equal('node2', result[1].name)
326
+ end
327
+ end
328
+
329
+ def test_casting
330
+ assert_equal 70, do_method_call(@direct_controller, 'Add', "50", "20")
331
+ assert_equal false, @direct_controller.struct_pass_value
332
+ person = DispatcherTest::Person.new(:id => 1, :name => 'test')
333
+ result = do_method_call(@direct_controller, 'StructPass', person)
334
+ assert(nil == result || true == result)
335
+ assert_equal person, @direct_controller.struct_pass_value
336
+ assert !person.equal?(@direct_controller.struct_pass_value)
337
+ result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test'})
338
+ case @protocol
339
+ when ActionWebService::Protocol::Soap::SoapProtocol
340
+ assert_equal(person, @direct_controller.struct_pass_value)
341
+ assert !person.equal?(@direct_controller.struct_pass_value)
342
+ when ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
343
+ assert_equal(person, @direct_controller.struct_pass_value)
344
+ assert !person.equal?(@direct_controller.struct_pass_value)
345
+ end
346
+ assert_equal person, do_method_call(@direct_controller, 'HashStructReturn')[0]
347
+ result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test', 'nonexistent_attribute' => 'value'})
348
+ case @protocol
349
+ when ActionWebService::Protocol::Soap::SoapProtocol
350
+ assert_equal(person, @direct_controller.struct_pass_value)
351
+ assert !person.equal?(@direct_controller.struct_pass_value)
352
+ when ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
353
+ assert_equal(person, @direct_controller.struct_pass_value)
354
+ assert !person.equal?(@direct_controller.struct_pass_value)
328
355
  end
329
356
  end
330
357
 
358
+ def test_logging
359
+ buf = ""
360
+ ActionController::Base.logger = Logger.new(StringIO.new(buf))
361
+ test_casting
362
+ test_garbage_request
363
+ test_exception_marshaling
364
+ ActionController::Base.logger = nil
365
+ assert_match /Web Service Response/, buf
366
+ assert_match /Web Service Request/, buf
367
+ end
368
+
331
369
  protected
332
370
  def service_name(container)
333
371
  raise NotImplementedError
@@ -342,37 +380,53 @@ module DispatcherCommonTests
342
380
  end
343
381
 
344
382
  def do_method_call(container, public_method_name, *params)
383
+ request_env = {}
345
384
  mode = container.web_service_dispatching_mode
346
385
  case mode
347
386
  when :direct
387
+ service_name = service_name(container)
348
388
  api = container.class.web_service_api
389
+ method = api.public_api_method_instance(public_method_name)
349
390
  when :delegated
350
- api = container.web_service_object(service_name(container)).class.web_service_api
391
+ service_name = service_name(container)
392
+ api = container.web_service_object(service_name).class.web_service_api
393
+ method = api.public_api_method_instance(public_method_name)
351
394
  when :layered
352
395
  service_name = nil
396
+ real_method_name = nil
353
397
  if public_method_name =~ /^([^\.]+)\.(.*)$/
354
398
  service_name = $1
399
+ real_method_name = $2
400
+ end
401
+ if @protocol.is_a? ActionWebService::Protocol::Soap::SoapProtocol
402
+ public_method_name = real_method_name
403
+ request_env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{real_method_name}"
355
404
  end
356
405
  api = container.web_service_object(service_name.to_sym).class.web_service_api
406
+ method = api.public_api_method_instance(real_method_name)
407
+ service_name = self.service_name(container)
357
408
  end
358
- info = api.api_methods[method_name] || {}
359
- params = params.dup
360
- ((info[:expects] || []) + (info[:returns] || [])).each do |spec|
361
- @marshaler.register_type(spec)
362
- end
363
- expects = info[:expects]
364
- (0..(params.length-1)).each do |i|
365
- type_binding = @marshaler.register_type(expects ? expects[i] : params[i].class)
366
- info = WS::ParamInfo.create(expects ? expects[i] : params[i].class, type_binding, i)
367
- params[i] = @marshaler.marshal(WS::Param.new(params[i], info))
409
+ @protocol.register_api(api)
410
+ virtual = false
411
+ unless method
412
+ virtual = true
413
+ method ||= ActionWebService::API::Method.new(public_method_name.underscore.to_sym, public_method_name, nil, nil)
368
414
  end
369
- body = @encoder.encode_rpc_call(public_method_name, params)
415
+ body = @protocol.encode_request(public_method_name, params.dup, method.expects)
370
416
  # puts body
371
- ap_request = create_ap_request(container, body, public_method_name, *params)
417
+ ap_request = @protocol.encode_action_pack_request(service_name, public_method_name, body, :request_class => ActionController::TestRequest)
418
+ ap_request.env.update(request_env)
372
419
  ap_response = ActionController::TestResponse.new
373
420
  container.process(ap_request, ap_response)
374
421
  # puts ap_response.body
375
- public_method_name, return_value = @encoder.decode_rpc_response(ap_response.body)
376
- @marshaler.unmarshal(return_value).value
422
+ public_method_name, return_value = @protocol.decode_response(ap_response.body)
423
+ unless is_exception?(return_value) || virtual
424
+ return_value = method.cast_returns(return_value)
425
+ end
426
+ if @protocol.is_a?(ActionWebService::Protocol::Soap::SoapProtocol)
427
+ # http://dev.rubyonrails.com/changeset/920
428
+ assert_match(/Response$/, public_method_name) unless public_method_name == "fault"
429
+ end
430
+ return_value
377
431
  end
378
432
  end