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