require File.dirname(__FILE__) + '/abstract_unit' module InvocationTest class API < ActionService::API::Base api_method :add, :expects => [:int, :int], :returns => [:int] api_method :transmogrify, :expects_and_returns => [:string] api_method :fail_with_reason api_method :fail_generic api_method :no_before api_method :no_after api_method :only_one api_method :only_two end class Service < ActionService::Base web_service_api API before_invocation :intercept_before, :except => [:no_before] after_invocation :intercept_after, :except => [:no_after] before_invocation :intercept_only, :only => [:only_one, :only_two] attr_accessor :before_invoked attr_accessor :after_invoked attr_accessor :only_invoked attr_accessor :invocation_result def initialize @before_invoked = nil @after_invoked = nil @only_invoked = nil @invocation_result = nil end def add(a, b) a + b end def transmogrify(str) str.upcase end def fail_with_reason end def fail_generic end def no_before 5 end def no_after end def only_one end def only_two end def not_public end protected def intercept_before(name, args) @before_invoked = name return [false, "permission denied"] if name == :fail_with_reason return false if name == :fail_generic end def intercept_after(name, args, result) @after_invoked = name @invocation_result = result end def intercept_only(name, args) raise "Interception error" unless name == :only_one || name == :only_two @only_invoked = name end end end class TC_Invocation < Test::Unit::TestCase include ActionService::Invocation def setup @service = InvocationTest::Service.new end def test_invocation assert(perform_invocation(:add, 5, 10) == 15) assert(perform_invocation(:transmogrify, "hello") == "HELLO") assert_raises(InvocationError) do perform_invocation(:not_public) end assert_raises(InvocationError) do perform_invocation(:nonexistent_method_xyzzy) end end def test_interceptor_registration assert(InvocationTest::Service.before_invocation_interceptors.length == 2) assert(InvocationTest::Service.after_invocation_interceptors.length == 1) end def test_interception assert(@service.before_invoked.nil? && @service.after_invoked.nil? && @service.only_invoked.nil? && @service.invocation_result.nil?) perform_invocation(:add, 20, 50) assert(@service.before_invoked == :add) assert(@service.after_invoked == :add) assert(@service.invocation_result == 70) end def test_interception_canceling reason = nil perform_invocation(:fail_with_reason){|r| reason = r} assert(@service.before_invoked == :fail_with_reason) assert(@service.after_invoked.nil?) assert(@service.invocation_result.nil?) assert(reason == "permission denied") reason = true @service.before_invoked = @service.after_invoked = @service.invocation_result = nil perform_invocation(:fail_generic){|r| reason = r} assert(@service.before_invoked == :fail_generic) assert(@service.after_invoked.nil?) assert(@service.invocation_result.nil?) assert(reason == true) end def test_interception_except_conditions perform_invocation(:no_before) assert(@service.before_invoked.nil?) assert(@service.after_invoked == :no_before) assert(@service.invocation_result == 5) @service.before_invoked = @service.after_invoked = @service.invocation_result = nil perform_invocation(:no_after) assert(@service.before_invoked == :no_after) assert(@service.after_invoked.nil?) assert(@service.invocation_result.nil?) end def test_interception_only_conditions assert(@service.only_invoked.nil?) perform_invocation(:only_one) assert(@service.only_invoked == :only_one) @service.only_invoked = nil perform_invocation(:only_two) assert(@service.only_invoked == :only_two) end private def perform_invocation(method_name, *args, &block) public_method_name = @service.class.web_service_api.public_api_method_name(method_name) args ||= [] request = InvocationRequest.new(ConcreteInvocation, public_method_name, method_name, args) @service.perform_invocation(request, &block) end end