提交 d43392a5 编写于 作者: L Leon Breedt

add action_web_service/test_invoke, will be used by for testing APIs in

a Rails project instance.


git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@830 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 b78283b3
*0.6.0* (Unreleased)
* Add action_controller/test_invoke, used for integrating AWS with the Rails testing infrastructure
* Allow passing through options to the SOAP RPC driver for the SOAP client
* Make the SOAP WS marshaler use #columns to decide which fields to marshal as well, avoids providing attributes brought in by associations
* Add <tt>ActionWebService::API::Base.allow_active_record_expects</tt> option, with a default of false. Setting this to true will allow specifying ActiveRecord::Base model classes in <tt>:expects</tt>. API writers should take care to validate the received ActiveRecord model objects when turning it on, and/or have an authentication mechanism in place to reduce the security risk.
......
= 0.7.0
- WS Test Integration
- WS Scaffolding
- WS Generators
- WS Test Integration
= 0.8.0
- Consumption of WSDL services
= Refactoring
- Port dispatcher tests to use test_invoke
- Don't have clean way to go from SOAP Class object to the xsd:NAME type
string -- NaHi possibly looking at remedying this situation
......@@ -12,6 +12,14 @@ def self.append_features(base) # :nodoc:
base.send(:include, ActionWebService::Dispatcher::InstanceMethods)
end
def self.layered_service_name(public_method_name) # :nodoc:
if public_method_name =~ /^([^\.]+)\.(.*)$/
$1
else
nil
end
end
module InstanceMethods # :nodoc:
private
def invoke_web_service_request(protocol_request)
......
require 'test/unit'
module Test
module Unit
class TestCase # :nodoc:
private
# invoke the specified API method
def invoke_direct(method_name, *args)
prepare_request('api', 'api', method_name, *args)
@controller.process(@request, @response)
decode_rpc_response
end
alias_method :invoke, :invoke_direct
# invoke the specified API method on the specified service
def invoke_delegated(service_name, method_name, *args)
prepare_request(service_name.to_s, service_name, method_name, *args)
@controller.process(@request, @response)
decode_rpc_response
end
# invoke the specified layered API method on the correct service
def invoke_layered(service_name, method_name, *args)
if protocol == :soap
raise "SOAP protocol support for :layered dispatching mode is not available"
end
prepare_request('api', service_name, method_name, *args)
@controller.process(@request, @response)
decode_rpc_response
end
# ---------------------- internal ---------------------------
def prepare_request(action, service_name, api_method_name, *args)
@request.request_parameters['action'] = action
@request.env['REQUEST_METHOD'] = 'POST'
@request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
@request.env['RAW_POST_DATA'] = encode_rpc_call(service_name, api_method_name, *args)
case protocol
when :soap
soap_action = "/#{@controller.controller_name}/#{service_name}/#{public_method_name(service_name, api_method_name)}"
@request.env['HTTP_SOAPACTION'] = soap_action
when :xmlrpc
@request.env.delete('HTTP_SOAPACTION')
end
end
def encode_rpc_call(service_name, api_method_name, *args)
case @controller.web_service_dispatching_mode
when :direct
api = @controller.class.web_service_api
when :delegated, :layered
api = @controller.web_service_object(service_name.to_sym).class.web_service_api
end
info = api.api_methods[api_method_name.to_sym]
((info[:expects] || []) + (info[:returns] || [])).each do |spec|
marshaler.register_type spec
end
expects = info[:expects]
args = args.dup
(0..(args.length-1)).each do |i|
type_binding = marshaler.register_type(expects ? expects[i] : args[i].class)
info = WS::ParamInfo.create(expects ? expects[i] : args[i].class, type_binding, i)
args[i] = marshaler.marshal(WS::Param.new(args[i], info))
end
encoder.encode_rpc_call(public_method_name(service_name, api_method_name), args)
end
def decode_rpc_response
public_method_name, return_value = encoder.decode_rpc_response(@response.body)
result = marshaler.unmarshal(return_value).value
unless @return_exceptions
exception = is_exception?(result)
raise exception if exception
end
result
end
def public_method_name(service_name, api_method_name)
public_name = service_api(service_name).public_api_method_name(api_method_name)
if @controller.web_service_dispatching_mode == :layered
'%s.%s' % [service_name.to_s, public_name]
else
public_name
end
end
def service_api(service_name)
case @controller.web_service_dispatching_mode
when :direct
@controller.class.web_service_api
when :delegated, :layered
@controller.web_service_object(service_name.to_sym).class.web_service_api
end
end
def protocol
@protocol ||= :soap
end
def marshaler
case protocol
when :soap
@soap_marshaler ||= WS::Marshaling::SoapMarshaler.new 'urn:ActionWebService'
when :xmlrpc
@xmlrpc_marshaler ||= WS::Marshaling::XmlRpcMarshaler.new
end
end
def encoder
case protocol
when :soap
@soap_encoder ||= WS::Encoding::SoapRpcEncoding.new 'urn:ActionWebService'
when :xmlrpc
@xmlrpc_encoder ||= WS::Encoding::XmlRpcEncoding.new
end
end
def is_exception?(obj)
case protocol
when :soap
(obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \
obj.detail.cause.is_a?(Exception)) ? obj.detail.cause : nil
when :xmlrpc
obj.is_a?(XMLRPC::FaultException) ? obj : nil
end
end
end
end
end
......@@ -62,7 +62,7 @@ def create_ap_request(container, body, public_method_name, *args)
test_request = ActionController::TestRequest.new
test_request.request_parameters['action'] = service_name(container)
test_request.env['REQUEST_METHOD'] = "POST"
test_request.env['HTTP_CONTENTTYPE'] = 'text/xml'
test_request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
test_request.env['HTTP_SOAPACTION'] = "/soap/#{service_name(container)}/#{public_method_name}"
test_request.env['RAW_POST_DATA'] = body
test_request
......
......@@ -33,7 +33,7 @@ def create_ap_request(container, body, public_method_name, *args)
test_request = ActionController::TestRequest.new
test_request.request_parameters['action'] = service_name(container)
test_request.env['REQUEST_METHOD'] = "POST"
test_request.env['HTTP_CONTENTTYPE'] = 'text/xml'
test_request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
test_request.env['RAW_POST_DATA'] = body
test_request
end
......
require File.dirname(__FILE__) + '/abstract_unit'
require 'action_web_service/test_invoke'
class TestInvokeAPI < ActionWebService::API::Base
api_method :add, :expects => [:int, :int], :returns => [:int]
end
class TestInvokeService < ActionWebService::Base
web_service_api TestInvokeAPI
attr :invoked
def add(a, b)
@invoked = true
a + b
end
end
class TestController < ActionController::Base
def rescue_action(e); raise e; end
end
class TestInvokeDirectController < TestController
web_service_api TestInvokeAPI
attr :invoked
def add
@invoked = true
@method_params[0] + @method_params[1]
end
end
class TestInvokeDelegatedController < TestController
web_service_dispatching_mode :delegated
web_service :service, TestInvokeService.new
end
class TestInvokeLayeredController < TestController
web_service_dispatching_mode :layered
web_service :one, TestInvokeService.new
web_service :two, TestInvokeService.new
end
class TestInvokeTest < Test::Unit::TestCase
def setup
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_direct_add
@controller = TestInvokeDirectController.new
assert_equal nil, @controller.invoked
result = invoke :add, 25, 25
assert_equal 50, result
assert_equal true, @controller.invoked
end
def test_delegated_add
@controller = TestInvokeDelegatedController.new
assert_equal nil, @controller.web_service_object(:service).invoked
result = invoke_delegated :service, :add, 100, 50
assert_equal 150, result
assert_equal true, @controller.web_service_object(:service).invoked
end
def test_layered_add
@protocol = :xmlrpc
@controller = TestInvokeLayeredController.new
[:one, :two].each do |service|
assert_equal nil, @controller.web_service_object(service).invoked
result = invoke_layered service, :add, 200, -50
assert_equal 150, result
assert_equal true, @controller.web_service_object(service).invoked
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册