diff options
author | francis <francis> | 2008-09-04 06:10:25 +0000 |
---|---|---|
committer | francis <francis> | 2008-09-04 06:10:25 +0000 |
commit | 5bde1025dc4d43ea53f63107b88711ebf8942408 (patch) | |
tree | 962c8b1fb32186fbd1ab15050ede8e560d9a63f6 /vendor/plugins/rspec/lib/spec/mocks | |
parent | ce2cf5ed73d81180e9f88d590daaa23989ee9472 (diff) |
rspec for rails 2.1
Diffstat (limited to 'vendor/plugins/rspec/lib/spec/mocks')
7 files changed, 111 insertions, 25 deletions
diff --git a/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb b/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb index 0e4777082..96ccf0f4a 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb @@ -1,7 +1,7 @@ module Spec module Mocks module ArgumentConstraintMatchers - + # Shortcut for creating an instance of Spec::Mocks::DuckTypeArgConstraint def duck_type(*args) DuckTypeArgConstraint.new(*args) @@ -19,6 +19,10 @@ module Spec BooleanArgConstraint.new(nil) end + def hash_including(expected={}) + HashIncludingConstraint.new(expected) + end + def no_args NoArgsConstraint.new end diff --git a/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb b/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb index 34a1d4d03..b3fdcc80d 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb @@ -108,6 +108,32 @@ module Spec "duck_type" end end + + class HashIncludingConstraint + def initialize(expected) + @expected = expected + end + + def ==(actual) + @expected.each do | key, value | + # check key for case that value evaluates to nil + return false unless actual.has_key?(key) && actual[key] == value + end + true + rescue NoMethodError => ex + return false + end + + def matches?(value) + self == value + end + + def description + "hash_including(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})" + end + + end + class ArgumentExpectation attr_reader :args diff --git a/vendor/plugins/rspec/lib/spec/mocks/extensions.rb b/vendor/plugins/rspec/lib/spec/mocks/extensions.rb new file mode 100644 index 000000000..6fd51a272 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/mocks/extensions.rb @@ -0,0 +1 @@ +require 'spec/mocks/extensions/object' diff --git a/vendor/plugins/rspec/lib/spec/mocks/framework.rb b/vendor/plugins/rspec/lib/spec/mocks/framework.rb new file mode 100644 index 000000000..92089673a --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/mocks/framework.rb @@ -0,0 +1,15 @@ +# Require everything except the global extensions of class and object. This +# supports wrapping rspec's mocking functionality without invading every +# object in the system. + +require 'spec/mocks/methods' +require 'spec/mocks/argument_constraint_matchers' +require 'spec/mocks/spec_methods' +require 'spec/mocks/proxy' +require 'spec/mocks/mock' +require 'spec/mocks/argument_expectation' +require 'spec/mocks/message_expectation' +require 'spec/mocks/order_group' +require 'spec/mocks/errors' +require 'spec/mocks/error_generator' +require 'spec/mocks/space' diff --git a/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb b/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb index 6bd2f1c32..0b10290b3 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb @@ -72,12 +72,18 @@ module Spec end def invoke(args, block) + if @expected_received_count == 0 + @actual_received_count += 1 + @error_generator.raise_expectation_error @sym, @expected_received_count, @actual_received_count, *args + end + @order_group.handle_order_constraint self begin Kernel::raise @exception_to_raise unless @exception_to_raise.nil? Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil? + if !@method_block.nil? default_return_val = invoke_method_block(args) elsif @args_to_yield.size > 0 @@ -112,12 +118,14 @@ module Spec if block.nil? @error_generator.raise_missing_block_error @args_to_yield end + value = nil @args_to_yield.each do |args_to_yield_this_time| if block.arity > -1 && args_to_yield_this_time.length != block.arity @error_generator.raise_wrong_arity_error args_to_yield_this_time, block.arity end - block.call(*args_to_yield_this_time) + value = block.call(*args_to_yield_this_time) end + value end def invoke_consecutive_return_block(args, block) @@ -147,9 +155,8 @@ module Spec @sym == sym and not @args_expectation.check_args(args) end - def verify_messages_received - return if ignoring_args? || matches_exact_count? || - matches_at_least_count? || matches_at_most_count? + def verify_messages_received + return if expected_messages_received? generate_error rescue Spec::Mocks::MockExpectationError => error @@ -157,6 +164,11 @@ module Spec Kernel::raise error end + def expected_messages_received? + ignoring_args? || matches_exact_count? || + matches_at_least_count? || matches_at_most_count? + end + def ignoring_args? @expected_received_count == :any end @@ -173,8 +185,20 @@ module Spec @expected_received_count == @actual_received_count end + def similar_messages + @similar_messages ||= [] + end + + def advise(args, block) + similar_messages << args + end + def generate_error - @error_generator.raise_expectation_error(@sym, @expected_received_count, @actual_received_count, *@args_expectation.args) + if similar_messages.empty? + @error_generator.raise_expectation_error(@sym, @expected_received_count, @actual_received_count, *@args_expectation.args) + else + @error_generator.raise_unexpected_message_args_error(self, *@similar_messages.first) + end end def with(*args, &block) diff --git a/vendor/plugins/rspec/lib/spec/mocks/mock.rb b/vendor/plugins/rspec/lib/spec/mocks/mock.rb index f029b1b8f..d0b5f204d 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/mock.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/mock.rb @@ -3,19 +3,21 @@ module Spec class Mock include Methods - # Creates a new mock with a +name+ (that will be used in error messages only) - # == Options: - # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving null object allowing any message to be sent to it. + # Creates a new mock with a +name+ (that will be used in error messages + # only) == Options: + # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving + # null object allowing any message to be sent to it. def initialize(name, stubs_and_options={}) @name = name @options = parse_options(stubs_and_options) assign_stubs(stubs_and_options) end - # This allows for comparing the mock to other objects that proxy - # such as ActiveRecords belongs_to proxy objects - # By making the other object run the comparison, we're sure the call gets delegated to the proxy target - # This is an unfortunate side effect from ActiveRecord, but this should be safe unless the RHS redefines == in a nonsensical manner + # This allows for comparing the mock to other objects that proxy such as + # ActiveRecords belongs_to proxy objects By making the other object run + # the comparison, we're sure the call gets delegated to the proxy target + # This is an unfortunate side effect from ActiveRecord, but this should + # be safe unless the RHS redefines == in a nonsensical manner def ==(other) other == __mock_proxy end diff --git a/vendor/plugins/rspec/lib/spec/mocks/proxy.rb b/vendor/plugins/rspec/lib/spec/mocks/proxy.rb index 03db3b113..45b96a30b 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/proxy.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/proxy.rb @@ -63,10 +63,14 @@ module Spec def message_received(sym, *args, &block) if expectation = find_matching_expectation(sym, *args) expectation.invoke(args, block) - elsif stub = find_matching_method_stub(sym, *args) + elsif (stub = find_matching_method_stub(sym, *args)) + if expectation = find_almost_matching_expectation(sym, *args) + expectation.advise(args, block) unless expectation.expected_messages_received? + end stub.invoke([], block) elsif expectation = find_almost_matching_expectation(sym, *args) - raise_unexpected_message_args_error(expectation, *args) unless has_negative_expectation?(sym) unless null_object? + expectation.advise(args, block) if null_object? unless expectation.expected_messages_received? + raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(sym) or null_object?) else @target.send :method_missing, sym, *args, &block end @@ -88,18 +92,20 @@ module Spec end def define_expected_method(sym) - if target_responds_to?(sym) && !metaclass.method_defined?(munge(sym)) + visibility_string = "#{visibility(sym)} :#{sym}" + if target_responds_to?(sym) && !target_metaclass.method_defined?(munge(sym)) munged_sym = munge(sym) - metaclass.instance_eval do + target_metaclass.instance_eval do alias_method munged_sym, sym if method_defined?(sym.to_s) end @proxied_methods << sym end - metaclass_eval(<<-EOF, __FILE__, __LINE__) + target_metaclass.class_eval(<<-EOF, __FILE__, __LINE__) def #{sym}(*args, &block) __mock_proxy.message_received :#{sym}, *args, &block end + #{visibility_string} EOF end @@ -109,6 +115,18 @@ module Spec return @target.respond_to?(sym) end + def visibility(sym) + if Mock === @target + 'public' + elsif target_metaclass.private_method_defined?(sym) + 'private' + elsif target_metaclass.protected_method_defined?(sym) + 'protected' + else + 'public' + end + end + def munge(sym) "proxied_by_rspec__#{sym.to_s}".to_sym end @@ -125,12 +143,8 @@ module Spec @proxied_methods.clear end - def metaclass_eval(str, filename, lineno) - metaclass.class_eval(str, filename, lineno) - end - - def metaclass - (class << @target; self; end) + def target_metaclass + class << @target; self; end end def verify_expectations @@ -142,7 +156,7 @@ module Spec def reset_proxied_methods @proxied_methods.each do |sym| munged_sym = munge(sym) - metaclass.instance_eval do + target_metaclass.instance_eval do if method_defined?(munged_sym.to_s) alias_method sym, munged_sym undef_method munged_sym |