lib/rspec/mocks/verifying_proxy.rb in rspec-mocks-3.0.0.beta1 vs lib/rspec/mocks/verifying_proxy.rb in rspec-mocks-3.0.0.beta2

- old
+ new

@@ -2,10 +2,11 @@ require 'rspec/mocks/method_reference' module RSpec module Mocks + # @api private module VerifyingProxyMethods def add_stub(location, method_name, opts={}, &implementation) ensure_implemented(method_name) super end @@ -19,25 +20,32 @@ ensure_implemented(method_name) super end def ensure_implemented(method_name) - return unless @doubled_module.defined? - - method_reference[method_name].when_unimplemented do + if method_reference[method_name].unimplemented? @error_generator.raise_unimplemented_error( @doubled_module, method_name ) end end + + def ensure_publicly_implemented(method_name, object) + ensure_implemented(method_name) + visibility = method_reference[method_name].visibility + + unless visibility == :public + @error_generator.raise_non_public_error(method_name, visibility) + end + end end # A verifying proxy mostly acts like a normal proxy, except that it # contains extra logic to try and determine the validity of any expectation # set on it. This includes whether or not methods have been defined and the - # arity of method calls. + # validatiy of arguments on method calls. # # In all other ways this behaves like a normal proxy. It only adds the # verification behaviour to specific methods then delegates to the parent # implementation. # @@ -54,11 +62,11 @@ @object = object @doubled_module = name @method_reference_class = method_reference_class # A custom method double is required to pass through a way to lookup - # methods to determine their arity. This is only relevant if the doubled + # methods to determine their parameters. This is only relevant if the doubled # class is loaded. @method_doubles = Hash.new do |h, k| h[k] = VerifyingMethodDouble.new(@object, k, self, method_reference[k]) end end @@ -66,21 +74,26 @@ def method_reference @method_reference ||= Hash.new do |h, k| h[k] = @method_reference_class.new(@doubled_module, k) end end + + def visibility_for(method_name) + method_reference[method_name].visibility + end end - class VerifyingPartialMockProxy < PartialMockProxy + # @api private + class VerifyingPartialDoubleProxy < PartialDoubleProxy include VerifyingProxyMethods def initialize(object, expectation_ordering) super(object, expectation_ordering) @doubled_module = DirectObjectReference.new(object) # A custom method double is required to pass through a way to lookup - # methods to determine their arity. + # methods to determine their parameters. @method_doubles = Hash.new do |h, k| h[k] = VerifyingExistingMethodDouble.new(object, k, self) end end @@ -103,33 +116,33 @@ def add_expectation(*arg) super.tap { |x| x.method_reference = @method_reference } end def proxy_method_invoked(obj, *args, &block) - ensure_arity!(args.length) + validate_arguments!(args) super end private - def ensure_arity!(arity) - @method_reference.when_defined do |method| - calculator = ArityCalculator.new(method) - unless calculator.within_range?(arity) - raise ArgumentError, "wrong number of arguments (#{arity} for #{method.arity})" + def validate_arguments!(actual_args) + @method_reference.with_signature do |signature| + verifier = MethodSignatureVerifier.new(signature, actual_args) + unless verifier.valid? + raise ArgumentError, verifier.error_message end end end end - # @api private - # # A VerifyingMethodDouble fetches the method to verify against from the # original object, using a MethodReference. This works for pure doubles, # but when the original object is itself the one being modified we need to # collapse the reference and the method double into a single object so that # we can access the original pristine method definition. + # + # @api private class VerifyingExistingMethodDouble < VerifyingMethodDouble def initialize(object, method_name, proxy) super(object, method_name, proxy, self) @valid_method = object.respond_to?(method_name) @@ -137,15 +150,15 @@ # Trigger an eager find of the original method since if we find it any # later we end up getting a stubbed method with incorrect arity. save_original_method! end - def when_defined - yield original_method + def with_signature + yield MethodSignature.new(original_method) end - def when_unimplemented - yield unless @valid_method + def unimplemented? + !@valid_method end end end end