Hello community,
here is the log from the commit of package rubygem-rspec-mocks for
openSUSE:Factory checked in at 2015-06-15 17:45:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-rspec-mocks (Old)
and /work/SRC/openSUSE:Factory/.rubygem-rspec-mocks.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-rspec-mocks"
Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-rspec-mocks/rubygem-rspec-mocks.changes
2015-03-01 14:57:59.000000000 +0100
+++
/work/SRC/openSUSE:Factory/.rubygem-rspec-mocks.new/rubygem-rspec-mocks.changes
2015-06-15 17:45:49.000000000 +0200
@@ -1,0 +2,53 @@
+Sat Jun 13 04:35:08 UTC 2015 - [email protected]
+
+- updated to version 3.3.0
+ see installed Changelog.md
+
+ ### 3.3.0 / 2015-06-12
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.1...v3.3.0)
+
+ Enhancements:
+
+ * When stubbing `new` on `MyClass` or `class_double(MyClass)`, use the
+ method signature from `MyClass#initialize` to verify arguments.
+ (Myron Marston, #886)
+ * Use matcher descriptions when generating description of received arguments
+ for mock expectation failures. (Tim Wade, #891)
+ * Avoid loading `stringio` unnecessarily. (Myron Marston, #894)
+ * Verifying doubles failure messages now distinguish between class and
instance
+ level methods. (Tim Wade, #896, #908)
+ * Improve mock expectation failure messages so that it combines both
+ number of times and the received arguments in the output. (John Ceh, #918)
+ * Improve how test doubles are represented in failure messages.
+ (Siva Gollapalli, Myron Marston, #932)
+ * Rename `RSpec::Mocks::Configuration#when_declaring_verifying_double` to
+ `RSpec::Mocks::Configuration#before_verifying_doubles` and utilise when
+ verifying partial doubles. (Jon Rowe, #940)
+ * Use rspec-support's `ObjectFormatter` for improved formatting of
+ arguments in failure messages so that, for example, full time
+ precisions is displayed for time objects. (Gavin Miller, Myron Marston,
#955)
+
+ Bug Fixes:
+
+ * Ensure expectations that raise eagerly also raise during RSpec
verification.
+ This means that if exceptions are caught inside test execution the test
will
+ still fail. (Sam Phippen, #884)
+ * Fix `have_received(msg).with(args).exactly(n).times` and
+ `receive(msg).with(args).exactly(n).times` failure messages
+ for when the message was received the wrong number of times with
+ the specified args, and also received additional times with other
+ arguments. Previously it confusingly listed the arguments as being
+ mis-matched (even when the double was allowed to receive with any
+ args) rather than listing the count. (John Ceh, #918)
+ * Fix `any_args`/`anything` support so that we avoid calling `obj ==
anything`
+ on user objects that may have improperly implemented `==` in a way that
+ raises errors. (Myron Marston, #924)
+ * Fix edge case involving stubbing the same method on a class and a subclass
+ which previously hit a `NoMethodError` internally in RSpec. (Myron Marston
#954)
+ * Fix edge case where the message received count would be incremented
multiple
+ times for one failure. (Myron Marston, #957)
+ * Fix failure messages for when spies received the expected message with
+ different arguments and also received another message. (MaurĂcio Linhares,
#960)
+ * Silence whitespace-only diffs. (Myron Marston, #969)
+
+-------------------------------------------------------------------
Old:
----
rspec-mocks-3.2.1.gem
New:
----
rspec-mocks-3.3.0.gem
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ rubygem-rspec-mocks.spec ++++++
--- /var/tmp/diff_new_pack.3ZrT1g/_old 2015-06-15 17:45:50.000000000 +0200
+++ /var/tmp/diff_new_pack.3ZrT1g/_new 2015-06-15 17:45:50.000000000 +0200
@@ -24,7 +24,7 @@
#
Name: rubygem-rspec-mocks
-Version: 3.2.1
+Version: 3.3.0
Release: 0
%define mod_name rspec-mocks
%define mod_full_name %{mod_name}-%{version}
++++++ rspec-mocks-3.2.1.gem -> rspec-mocks-3.3.0.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Changelog.md new/Changelog.md
--- old/Changelog.md 2015-02-24 04:24:29.000000000 +0100
+++ new/Changelog.md 2015-06-12 17:05:16.000000000 +0200
@@ -1,3 +1,50 @@
+### 3.3.0 / 2015-06-12
+[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.1...v3.3.0)
+
+Enhancements:
+
+* When stubbing `new` on `MyClass` or `class_double(MyClass)`, use the
+ method signature from `MyClass#initialize` to verify arguments.
+ (Myron Marston, #886)
+* Use matcher descriptions when generating description of received arguments
+ for mock expectation failures. (Tim Wade, #891)
+* Avoid loading `stringio` unnecessarily. (Myron Marston, #894)
+* Verifying doubles failure messages now distinguish between class and instance
+ level methods. (Tim Wade, #896, #908)
+* Improve mock expectation failure messages so that it combines both
+ number of times and the received arguments in the output. (John Ceh, #918)
+* Improve how test doubles are represented in failure messages.
+ (Siva Gollapalli, Myron Marston, #932)
+* Rename `RSpec::Mocks::Configuration#when_declaring_verifying_double` to
+ `RSpec::Mocks::Configuration#before_verifying_doubles` and utilise when
+ verifying partial doubles. (Jon Rowe, #940)
+* Use rspec-support's `ObjectFormatter` for improved formatting of
+ arguments in failure messages so that, for example, full time
+ precisions is displayed for time objects. (Gavin Miller, Myron Marston, #955)
+
+Bug Fixes:
+
+* Ensure expectations that raise eagerly also raise during RSpec verification.
+ This means that if exceptions are caught inside test execution the test will
+ still fail. (Sam Phippen, #884)
+* Fix `have_received(msg).with(args).exactly(n).times` and
+ `receive(msg).with(args).exactly(n).times` failure messages
+ for when the message was received the wrong number of times with
+ the specified args, and also received additional times with other
+ arguments. Previously it confusingly listed the arguments as being
+ mis-matched (even when the double was allowed to receive with any
+ args) rather than listing the count. (John Ceh, #918)
+* Fix `any_args`/`anything` support so that we avoid calling `obj == anything`
+ on user objects that may have improperly implemented `==` in a way that
+ raises errors. (Myron Marston, #924)
+* Fix edge case involving stubbing the same method on a class and a subclass
+ which previously hit a `NoMethodError` internally in RSpec. (Myron Marston
#954)
+* Fix edge case where the message received count would be incremented multiple
+ times for one failure. (Myron Marston, #957)
+* Fix failure messages for when spies received the expected message with
+ different arguments and also received another message. (MaurĂcio Linhares,
#960)
+* Silence whitespace-only diffs. (Myron Marston, #969)
+
### 3.2.1 / 2015-02-23
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.0...v3.2.1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md 2015-02-24 04:24:29.000000000 +0100
+++ new/README.md 2015-06-12 17:05:16.000000000 +0200
@@ -417,8 +417,8 @@
you are interested in learning more, here is some recommended reading:
* Mock Objects: http://www.mockobjects.com/
-* Endo-Testing:
http://stalatest.googlecode.com/svn/trunk/Literatur/mockobjects.pdf
-* Mock Roles, Not Objects: http://jmock.org/oopsla2004.pdf
+* Endo-Testing:
http://www.ccs.neu.edu/research/demeter/related-work/extreme-programming/MockObjectsFinal.PDF
+* Mock Roles, Not Objects: http://www.jmock.org/oopsla2004.pdf
* Test Double: http://www.martinfowler.com/bliki/TestDouble.html
* Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html
* Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html
Files old/checksums.yaml.gz and new/checksums.yaml.gz differ
Files old/checksums.yaml.gz.sig and new/checksums.yaml.gz.sig differ
Files old/data.tar.gz.sig and new/data.tar.gz.sig differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/any_instance/chain.rb
new/lib/rspec/mocks/any_instance/chain.rb
--- old/lib/rspec/mocks/any_instance/chain.rb 2015-02-24 04:24:29.000000000
+0100
+++ new/lib/rspec/mocks/any_instance/chain.rb 2015-06-12 17:05:16.000000000
+0200
@@ -76,7 +76,7 @@
end
def never
-
ErrorGenerator.raise_double_negation_error("expect_any_instance_of(MyClass)")
if negated?
+
AnyInstance.error_generator.raise_double_negation_error("expect_any_instance_of(MyClass)")
if negated?
super
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/any_instance/error_generator.rb
new/lib/rspec/mocks/any_instance/error_generator.rb
--- old/lib/rspec/mocks/any_instance/error_generator.rb 1970-01-01
01:00:00.000000000 +0100
+++ new/lib/rspec/mocks/any_instance/error_generator.rb 2015-06-12
17:05:16.000000000 +0200
@@ -0,0 +1,31 @@
+module RSpec
+ module Mocks
+ module AnyInstance
+ # @private
+ class ErrorGenerator < ::RSpec::Mocks::ErrorGenerator
+ def
raise_second_instance_received_message_error(unfulfilled_expectations)
+ __raise "Exactly one instance should have received the following " \
+ "message(s) but didn't:
#{unfulfilled_expectations.sort.join(', ')}"
+ end
+
+ def raise_does_not_implement_error(klass, method_name)
+ __raise "#{klass} does not implement ##{method_name}"
+ end
+
+ def
raise_message_already_received_by_other_instance_error(method_name,
object_inspect, invoked_instance)
+ __raise "The message '#{method_name}' was received by
#{object_inspect} " \
+ "but has already been received by #{invoked_instance}"
+ end
+
+ def raise_not_supported_with_prepend_error(method_name, problem_mod)
+ __raise "Using `any_instance` to stub a method (#{method_name}) that
has been " \
+ "defined on a prepended module (#{problem_mod}) is not
supported."
+ end
+ end
+
+ def self.error_generator
+ @error_generator ||= ErrorGenerator.new
+ end
+ end
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/any_instance/message_chains.rb
new/lib/rspec/mocks/any_instance/message_chains.rb
--- old/lib/rspec/mocks/any_instance/message_chains.rb 2015-02-24
04:24:29.000000000 +0100
+++ new/lib/rspec/mocks/any_instance/message_chains.rb 2015-06-12
17:05:16.000000000 +0200
@@ -75,9 +75,7 @@
return unless ExpectationChain === instance
return if @instance_with_expectation.equal?(instance)
- raise RSpec::Mocks::MockExpectationError,
- "Exactly one instance should have received the following " \
- "message(s) but didn't:
#{unfulfilled_expectations.sort.join(', ')}"
+
AnyInstance.error_generator.raise_second_instance_received_message_error(unfulfilled_expectations)
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/any_instance/recorder.rb
new/lib/rspec/mocks/any_instance/recorder.rb
--- old/lib/rspec/mocks/any_instance/recorder.rb 2015-02-24
04:24:29.000000000 +0100
+++ new/lib/rspec/mocks/any_instance/recorder.rb 2015-06-12
17:05:16.000000000 +0200
@@ -76,7 +76,7 @@
# @see Methods#unstub
def unstub(method_name)
unless @observed_methods.include?(method_name.to_sym)
- raise RSpec::Mocks::MockExpectationError, "The method
`#{method_name}` was not stubbed or was already unstubbed"
+
AnyInstance.error_generator.raise_method_not_stubbed_error(method_name)
end
message_chains.remove_stub_chains_for!(method_name)
stubs[method_name].clear
@@ -91,9 +91,7 @@
return unless @expectation_set
return if message_chains.all_expectations_fulfilled?
- raise RSpec::Mocks::MockExpectationError,
- "Exactly one instance should have received the following " \
- "message(s) but didn't:
#{message_chains.unfulfilled_expectations.sort.join(', ')}"
+
AnyInstance.error_generator.raise_second_instance_received_message_error(message_chains.unfulfilled_expectations)
end
# @private
@@ -221,8 +219,7 @@
if RSpec::Mocks.configuration.verify_partial_doubles?
unless public_protected_or_private_method_defined?(method_name)
- raise MockExpectationError,
- "#{@klass} does not implement ##{method_name}"
+
AnyInstance.error_generator.raise_does_not_implement_error(@klass, method_name)
end
end
@@ -242,7 +239,9 @@
@klass.__send__(:define_method, method_name) do |*_args, &_blk|
invoked_instance = recorder.instance_that_received(method_name)
inspect = "#<#{self.class}:#{object_id} #{instance_variables.map {
|name| "#{name}=#{instance_variable_get name}" }.join(', ')}>"
- raise RSpec::Mocks::MockExpectationError, "The message
'#{method_name}' was received by #{inspect} but has already been received by
#{invoked_instance}"
+
AnyInstance.error_generator.raise_message_already_received_by_other_instance_error(
+ method_name, inspect, invoked_instance
+ )
end
end
@@ -252,9 +251,7 @@
problem_mod = prepended_modules.find { |mod|
mod.method_defined?(method_name) }
return unless problem_mod
- raise RSpec::Mocks::MockExpectationError,
- "Using `any_instance` to stub a method (#{method_name}) that
has been " \
- "defined on a prepended module (#{problem_mod}) is not
supported."
+
AnyInstance.error_generator.raise_not_supported_with_prepend_error(method_name,
problem_mod)
end
else
def allow_no_prepended_module_definition_of(_method_name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/any_instance.rb
new/lib/rspec/mocks/any_instance.rb
--- old/lib/rspec/mocks/any_instance.rb 2015-02-24 04:24:29.000000000 +0100
+++ new/lib/rspec/mocks/any_instance.rb 2015-06-12 17:05:16.000000000 +0200
@@ -1,5 +1,6 @@
%w[
any_instance/chain
+ any_instance/error_generator
any_instance/stub_chain
any_instance/stub_chain_chain
any_instance/expect_chain_chain
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/argument_list_matcher.rb
new/lib/rspec/mocks/argument_list_matcher.rb
--- old/lib/rspec/mocks/argument_list_matcher.rb 2015-02-24
04:24:29.000000000 +0100
+++ new/lib/rspec/mocks/argument_list_matcher.rb 2015-06-12
17:05:16.000000000 +0200
@@ -64,7 +64,7 @@
def resolve_expected_args_based_on(actual_args)
return [] if [ArgumentMatchers::NoArgsMatcher::INSTANCE] ==
expected_args
- any_args_index =
expected_args.index(ArgumentMatchers::AnyArgsMatcher::INSTANCE)
+ any_args_index = expected_args.index { |a|
ArgumentMatchers::AnyArgsMatcher::INSTANCE == a }
return expected_args unless any_args_index
replace_any_args_with_splat_of_anything(any_args_index,
actual_args.count)
@@ -81,10 +81,10 @@
end
def ensure_expected_args_valid!
- if expected_args.count(ArgumentMatchers::AnyArgsMatcher::INSTANCE) > 1
+ if expected_args.count { |a|
ArgumentMatchers::AnyArgsMatcher::INSTANCE == a } > 1
raise ArgumentError, "`any_args` can only be passed to " \
"`with` once but you have passed it multiple times."
- elsif expected_args.count > 1 &&
expected_args.include?(ArgumentMatchers::NoArgsMatcher::INSTANCE)
+ elsif expected_args.count > 1 && expected_args.any? { |a|
ArgumentMatchers::NoArgsMatcher::INSTANCE == a }
raise ArgumentError, "`no_args` can only be passed as a " \
"singleton argument to `with` (i.e. `with(no_args)`), " \
"but you have passed additional arguments."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/configuration.rb
new/lib/rspec/mocks/configuration.rb
--- old/lib/rspec/mocks/configuration.rb 2015-02-24 04:24:29.000000000
+0100
+++ new/lib/rspec/mocks/configuration.rb 2015-06-12 17:05:16.000000000
+0200
@@ -103,17 +103,18 @@
# Provides a way to perform customisations when verifying doubles.
#
# @example
- # RSpec::Mocks.configuration.when_declaring_verifying_double do |ref|
+ # RSpec::Mocks.configuration.before_verifying_doubles do |ref|
# ref.some_method!
# end
- def when_declaring_verifying_double(&block)
- verifying_double_declaration_callbacks << block
+ def before_verifying_doubles(&block)
+ verifying_double_callbacks << block
end
+ alias :when_declaring_verifying_double :before_verifying_doubles
# @api private
# Returns an array of blocks to call when verifying doubles
- def verifying_double_declaration_callbacks
- @verifying_double_declaration_callbacks ||= []
+ def verifying_double_callbacks
+ @verifying_double_callbacks ||= []
end
def transfer_nested_constants?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/error_generator.rb
new/lib/rspec/mocks/error_generator.rb
--- old/lib/rspec/mocks/error_generator.rb 2015-02-24 04:24:29.000000000
+0100
+++ new/lib/rspec/mocks/error_generator.rb 2015-06-12 17:05:16.000000000
+0200
@@ -1,4 +1,4 @@
-RSpec::Support.require_rspec_support 'differ'
+RSpec::Support.require_rspec_support "object_formatter"
module RSpec
module Mocks
@@ -36,9 +36,8 @@
class ErrorGenerator
attr_writer :opts
- def initialize(target, name)
+ def initialize(target=nil)
@target = target
- @name = name
end
# @private
@@ -47,41 +46,26 @@
end
# @private
- def raise_unexpected_message_error(message, *args)
- __raise "#{intro} received unexpected message
:#{message}#{arg_message(*args)}"
+ def raise_unexpected_message_error(message, args)
+ __raise "#{intro} received unexpected message :#{message} with
#{format_args(args)}"
end
# @private
- def raise_unexpected_message_args_error(expectation, *args)
- expected_args = format_args(*expectation.expected_args)
- actual_args = format_received_args(*args)
- diff = diff_message(expectation.expected_args, args)
-
- message = default_error_message(expectation, expected_args,
actual_args)
- message << "\nDiff:#{diff}" unless diff.empty?
-
- __raise message
+ def raise_unexpected_message_args_error(expectation,
args_for_multiple_calls, source_id=nil)
+ __raise error_message(expectation, args_for_multiple_calls), nil,
source_id
end
# @private
- def raise_missing_default_stub_error(expectation, *args)
- expected_args = format_args(*expectation.expected_args)
- actual_args = format_received_args(*args)
- diff = diff_message(expectation.expected_args, args)
-
- message = default_error_message(expectation, expected_args,
actual_args)
- message << "\nDiff:\n #{diff}" unless diff.empty?
+ def raise_missing_default_stub_error(expectation,
args_for_multiple_calls)
+ message = error_message(expectation, args_for_multiple_calls)
message << "\n Please stub a default value first if message might be
received with other args as well. \n"
__raise message
end
# @private
- def raise_similar_message_args_error(expectation,
*args_for_multiple_calls)
- expected_args = format_args(*expectation.expected_args)
- actual_args = args_for_multiple_calls.map { |a|
format_received_args(*a) }.join(", ")
-
- __raise(default_error_message(expectation, expected_args, actual_args))
+ def raise_similar_message_args_error(expectation,
args_for_multiple_calls, backtrace_line=nil)
+ __raise error_message(expectation, args_for_multiple_calls),
backtrace_line
end
def default_error_message(expectation, expected_args, actual_args)
@@ -95,19 +79,37 @@
# rubocop:disable Style/ParameterLists
# @private
- def raise_expectation_error(message, expected_received_count,
argument_list_matcher, actual_received_count, expectation_count_type, *args)
+ def raise_expectation_error(message, expected_received_count,
argument_list_matcher,
+ actual_received_count,
expectation_count_type, args,
+ backtrace_line=nil, source_id=nil)
expected_part =
expected_part_of_expectation_error(expected_received_count,
expectation_count_type, argument_list_matcher)
- received_part =
received_part_of_expectation_error(actual_received_count, *args)
- __raise "(#{intro}).#{message}#{format_args(*args)}\n
#{expected_part}\n #{received_part}"
+ received_part =
received_part_of_expectation_error(actual_received_count, args)
+ __raise "(#{intro(:unwrapped)}).#{message}#{format_args(args)}\n
#{expected_part}\n #{received_part}", backtrace_line, source_id
end
# rubocop:enable Style/ParameterLists
# @private
- def raise_unimplemented_error(doubled_module, method_name)
- __raise "%s does not implement: %s" % [
- doubled_module.description,
- method_name
- ]
+ def raise_unimplemented_error(doubled_module, method_name, object)
+ message = case object
+ when InstanceVerifyingDouble
+ "the %s class does not implement the instance method: %s"
<<
+ if ObjectMethodReference.for(doubled_module,
method_name).implemented?
+ ". Perhaps you meant to use `class_double` instead?"
+ else
+ ""
+ end
+ when ClassVerifyingDouble
+ "the %s class does not implement the class method: %s" <<
+ if InstanceMethodReference.for(doubled_module,
method_name).implemented?
+ ". Perhaps you meant to use `instance_double` instead?"
+ else
+ ""
+ end
+ else
+ "%s does not implement: %s"
+ end
+
+ __raise message % [doubled_module.description, method_name]
end
# @private
@@ -132,101 +134,131 @@
end
# @private
- def received_part_of_expectation_error(actual_received_count, *args)
- "received: #{count_message(actual_received_count)}" +
- actual_method_call_args_description(actual_received_count, args)
+ def describe_expectation(verb, message, expected_received_count,
_actual_received_count, args)
+ "#{verb} #{message}#{format_args(args)}
#{count_message(expected_received_count)}"
end
# @private
- def expected_part_of_expectation_error(expected_received_count,
expectation_count_type, argument_list_matcher)
- "expected: #{count_message(expected_received_count,
expectation_count_type)}" +
-
expected_method_call_args_description(argument_list_matcher.expected_args)
+ def raise_out_of_order_error(message)
+ __raise "#{intro} received :#{message} out of order"
end
# @private
- def actual_method_call_args_description(count, args)
- method_call_args_description(args) ||
- if count > 0 && args.length > 0
- " with arguments: #{args.inspect.gsub(/\A\[(.+)\]\z/, '(\1)')}"
- else
- ""
- end
+ def raise_missing_block_error(args_to_yield)
+ __raise "#{intro} asked to yield |#{arg_list(args_to_yield)}| but no
block was passed"
end
# @private
- def expected_method_call_args_description(args)
- method_call_args_description(args) ||
- if args.length > 0
- " with arguments: #{format_args(*args)}"
- else
- ""
- end
+ def raise_wrong_arity_error(args_to_yield, signature)
+ __raise "#{intro} yielded |#{arg_list(args_to_yield)}| to block with
#{signature.description}"
end
# @private
- def method_call_args_description(args)
- case args.first
- when ArgumentMatchers::AnyArgsMatcher then " with any arguments"
- when ArgumentMatchers::NoArgsMatcher then " with no arguments"
- end
+ def raise_only_valid_on_a_partial_double(method)
+ __raise "#{intro} is a pure test double. `#{method}` is only " \
+ "available on a partial double."
end
# @private
- def describe_expectation(verb, message, expected_received_count,
_actual_received_count, *args)
- "#{verb} #{message}#{format_args(*args)}
#{count_message(expected_received_count)}"
+ def raise_expectation_on_unstubbed_method(method)
+ __raise "#{intro} expected to have received #{method}, but that " \
+ "object is not a spy or method has not been stubbed."
end
# @private
- def raise_out_of_order_error(message)
- __raise "#{intro} received :#{message} out of order"
+ def raise_expectation_on_mocked_method(method)
+ __raise "#{intro} expected to have received #{method}, but that " \
+ "method has been mocked instead of stubbed or spied."
end
# @private
- def raise_block_failed_error(message, detail)
- __raise "#{intro} received :#{message} but passed block failed with:
#{detail}"
+ def raise_double_negation_error(wrapped_expression)
+ __raise "Isn't life confusing enough? You've already set a " \
+ "negative message expectation and now you are trying to " \
+ "negate it again with `never`. What does an expression like " \
+ "`#{wrapped_expression}.not_to receive(:msg).never` even mean?"
end
# @private
- def raise_missing_block_error(args_to_yield)
- __raise "#{intro} asked to yield |#{arg_list(*args_to_yield)}| but no
block was passed"
+ def raise_verifying_double_not_defined_error(ref)
+ notify(VerifyingDoubleNotDefinedError.new(
+ "#{ref.description.inspect} is not a defined constant. " \
+ "Perhaps you misspelt it? " \
+ "Disable check with `verify_doubled_constant_names` configuration
option."
+ ))
end
# @private
- def raise_wrong_arity_error(args_to_yield, signature)
- __raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with
#{signature.description}"
+ def raise_have_received_disallowed(type, reason)
+ __raise "Using #{type}(...) with the `have_received` " \
+ "matcher is not supported#{reason}."
end
# @private
- def raise_only_valid_on_a_partial_double(method)
- __raise "#{intro} is a pure test double. `#{method}` is only " \
- "available on a partial double."
+ def
raise_cant_constrain_count_for_negated_have_received_error(count_constraint)
+ __raise "can't use #{count_constraint} when negative"
end
# @private
- def raise_expectation_on_unstubbed_method(method)
- __raise "#{intro} expected to have received #{method}, but that " \
- "object is not a spy or method has not been stubbed."
+ def raise_method_not_stubbed_error(method_name)
+ __raise "The method `#{method_name}` was not stubbed or was already
unstubbed"
end
# @private
- def raise_expectation_on_mocked_method(method)
- __raise "#{intro} expected to have received #{method}, but that " \
- "method has been mocked instead of stubbed or spied."
- end
+ def raise_already_invoked_error(message, calling_customization)
+ error_message = "The message expectation for #{intro}.#{message} has
already been invoked " \
+ "and cannot be modified further (e.g. using
`#{calling_customization}`). All message expectation " \
+ "customizations must be applied before it is used for the first
time."
- def self.raise_double_negation_error(wrapped_expression)
- raise "Isn't life confusing enough? You've already set a " \
- "negative message expectation and now you are trying to " \
- "negate it again with `never`. What does an expression like " \
- "`#{wrapped_expression}.not_to receive(:msg).never` even mean?"
+ notify MockExpectationAlreadyInvokedError.new(error_message)
end
private
+ def received_part_of_expectation_error(actual_received_count, args)
+ "received: #{count_message(actual_received_count)}" +
+ method_call_args_description(args) do
+ actual_received_count > 0 && args.length > 0
+ end
+ end
+
+ def expected_part_of_expectation_error(expected_received_count,
expectation_count_type, argument_list_matcher)
+ "expected: #{count_message(expected_received_count,
expectation_count_type)}" +
+ method_call_args_description(argument_list_matcher.expected_args) do
+ argument_list_matcher.expected_args.length > 0
+ end
+ end
+
+ def method_call_args_description(args)
+ case args.first
+ when ArgumentMatchers::AnyArgsMatcher then " with any arguments"
+ when ArgumentMatchers::NoArgsMatcher then " with no arguments"
+ else
+ if yield
+ " with arguments: #{format_args(args)}"
+ else
+ ""
+ end
+ end
+ end
+
def unexpected_arguments_message(expected_args_string,
actual_args_string)
"with unexpected arguments\n expected: #{expected_args_string}\n
got: #{actual_args_string}"
end
+ def error_message(expectation, args_for_multiple_calls)
+ expected_args = format_args(expectation.expected_args)
+ actual_args = format_received_args(args_for_multiple_calls)
+ message = default_error_message(expectation, expected_args,
actual_args)
+
+ if args_for_multiple_calls.one?
+ diff = diff_message(expectation.expected_args,
args_for_multiple_calls.first)
+ message << "\nDiff:#{diff}" unless diff.strip.empty?
+ end
+
+ message
+ end
+
def diff_message(expected_args, actual_args)
formatted_expected_args = expected_args.map do |x|
RSpec::Support.rspec_description_for_object(x)
@@ -253,47 +285,54 @@
RSpec::Support::Differ.new(:color => RSpec::Mocks.configuration.color?)
end
- def intro
- if @name
- "Double #{@name.inspect}"
- elsif TestDouble === @target
- "Double"
- elsif Class === @target
- "<#{@target.inspect} (class)>"
- elsif @target
- @target
- else
- "nil"
+ def intro(unwrapped=false)
+ case @target
+ when TestDouble then TestDoubleFormatter.format(@target, unwrapped)
+ when Class then
+ formatted = "#{@target.inspect} (class)"
+ return formatted if unwrapped
+ "#<#{formatted}>"
+ when NilClass then "nil"
+ else @target
end
end
- def __raise(message)
+ def __raise(message, backtrace_line=nil, source_id=nil)
message = opts[:message] unless opts[:message].nil?
- Kernel.raise(RSpec::Mocks::MockExpectationError, message)
+ exception = RSpec::Mocks::MockExpectationError.new(message)
+ prepend_to_backtrace(exception, backtrace_line) if backtrace_line
+ notify exception, :source_id => source_id
end
- def arg_message(*args)
- " with " + format_args(*args)
- end
-
- def format_args(*args)
- args.empty? ? "(no args)" : "(" + arg_list(*args) + ")"
+ if RSpec::Support::Ruby.jruby?
+ def prepend_to_backtrace(exception, line)
+ raise exception
+ rescue RSpec::Mocks::MockExpectationError => with_backtrace
+ with_backtrace.backtrace.unshift(line)
+ end
+ else
+ def prepend_to_backtrace(exception, line)
+ exception.set_backtrace(caller.unshift line)
+ end
end
- def arg_list(*args)
- args.map { |arg| arg_has_valid_description?(arg) ? arg.description :
arg.inspect }.join(", ")
+ def notify(*args)
+ RSpec::Support.notify_failure(*args)
end
- def arg_has_valid_description?(arg)
- RSpec::Support.is_a_matcher?(arg) && arg.respond_to?(:description)
+ def format_args(args)
+ return "(no args)" if args.empty?
+ "(#{arg_list(args)})"
end
- def format_received_args(*args)
- args.empty? ? "(no args)" : "(" + received_arg_list(*args) + ")"
+ def arg_list(args)
+ args.map { |arg| RSpec::Support::ObjectFormatter.format(arg) }.join(",
")
end
- def received_arg_list(*args)
- args.map(&:inspect).join(", ")
+ def format_received_args(args_for_multiple_calls)
+ grouped_args(args_for_multiple_calls).map do |args_for_one_call, index|
+ "#{format_args(args_for_one_call)}#{group_count(index,
args_for_multiple_calls)}"
+ end.join("\n ")
end
def count_message(count, expectation_count_type=nil)
@@ -305,6 +344,19 @@
def times(count)
"#{count} time#{count == 1 ? '' : 's'}"
end
+
+ def grouped_args(args)
+ Hash[args.group_by { |x| x }.map { |k, v| [k, v.count] }]
+ end
+
+ def group_count(index, args)
+ " (#{times(index)})" if args.size > 1 || index > 1
+ end
+ end
+
+ # @private
+ def self.error_generator
+ @error_generator ||= ErrorGenerator.new
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/example_methods.rb
new/lib/rspec/mocks/example_methods.rb
--- old/lib/rspec/mocks/example_methods.rb 2015-02-24 04:24:29.000000000
+0100
+++ new/lib/rspec/mocks/example_methods.rb 2015-06-12 17:05:16.000000000
+0200
@@ -396,13 +396,10 @@
if RSpec::Mocks.configuration.verify_doubled_constant_names? &&
!ref.defined?
- raise VerifyingDoubleNotDefinedError,
- "#{ref.description.inspect} is not a defined constant. " \
- "Perhaps you misspelt it? " \
- "Disable check with `verify_doubled_constant_names`
configuration option."
+
RSpec::Mocks.error_generator.raise_verifying_double_not_defined_error(ref)
end
- RSpec::Mocks.configuration.verifying_double_declaration_callbacks.each
do |block|
+ RSpec::Mocks.configuration.verifying_double_callbacks.each do |block|
block.call(ref)
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/matchers/have_received.rb
new/lib/rspec/mocks/matchers/have_received.rb
--- old/lib/rspec/mocks/matchers/have_received.rb 2015-02-24
04:24:29.000000000 +0100
+++ new/lib/rspec/mocks/matchers/have_received.rb 2015-06-12
17:05:16.000000000 +0200
@@ -69,9 +69,7 @@
private
def disallow(type, reason="")
- raise RSpec::Mocks::MockExpectationError,
- "Using #{type}(...) with the `have_received` " \
- "matcher is not supported#{reason}."
+ RSpec::Mocks.error_generator.raise_have_received_disallowed(type,
reason)
end
def expect
@@ -88,8 +86,7 @@
def ensure_count_unconstrained
return unless count_constraint
- raise RSpec::Mocks::MockExpectationError,
- "can't use #{count_constraint} when negative"
+
RSpec::Mocks.error_generator.raise_cant_constrain_count_for_negated_have_received_error(count_constraint)
end
def count_constraint
@@ -99,10 +96,10 @@
end
def generate_failure_message
- mock_proxy.check_for_unexpected_arguments(@expectation)
- @expectation.generate_error
- rescue RSpec::Mocks::MockExpectationError => error
- error.message
+ RSpec::Support.with_failure_notifier(Proc.new { |err, _opt| return
err.message }) do
+ mock_proxy.check_for_unexpected_arguments(@expectation)
+ @expectation.generate_error
+ end
end
def expected_messages_received_in_order?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/message_chain.rb
new/lib/rspec/mocks/message_chain.rb
--- old/lib/rspec/mocks/message_chain.rb 2015-02-24 04:24:30.000000000
+0100
+++ new/lib/rspec/mocks/message_chain.rb 2015-06-12 17:05:16.000000000
+0200
@@ -30,10 +30,6 @@
private
- def expectation(_object, _message, &_return_block)
- raise NotImplementedError
- end
-
def chain_on(object, *chain, &block)
initialize(object, *chain, &block)
setup_chain
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/message_expectation.rb
new/lib/rspec/mocks/message_expectation.rb
--- old/lib/rspec/mocks/message_expectation.rb 2015-02-24 04:24:30.000000000
+0100
+++ new/lib/rspec/mocks/message_expectation.rb 2015-06-12 17:05:16.000000000
+0200
@@ -26,11 +26,13 @@
end
def verify_messages_received
- InsertOntoBacktrace.line(@backtrace_line) do
- unless @received
- @error_generator.raise_expectation_error(@message, 1,
ArgumentListMatcher::MATCH_ALL, 0, nil)
- end
- end
+ return if @received
+ @error_generator.raise_expectation_error(
+ @message, 1, ArgumentListMatcher::MATCH_ALL, 0, nil, [],
@backtrace_line
+ )
+ end
+
+ def unadvise(_)
end
end
@@ -115,7 +117,7 @@
@error_generator.raise_only_valid_on_a_partial_double(:and_call_original)
else
warn_about_stub_override if implementation.inner_action
- @implementation =
AndWrapOriginalImplementation.new(@method_double.original_method, block)
+ @implementation =
AndWrapOriginalImplementation.new(@method_double.original_implementation_callable,
block)
@yield_receiver_to_implementation_block = false
end
@@ -142,13 +144,9 @@
# allow(car).to receive(:go).and_raise(OutOfGas)
# allow(car).to receive(:go).and_raise(OutOfGas, "At least 2 oz of gas
needed to drive")
# allow(car).to receive(:go).and_raise(OutOfGas.new(2, :oz))
- def and_raise(exception=RuntimeError, message=nil)
+ def and_raise(*args)
raise_already_invoked_error_if_necessary(__method__)
- if exception.respond_to?(:exception)
- exception = message ? exception.exception(message) :
exception.exception
- end
-
- self.terminal_implementation_action = Proc.new { raise exception }
+ self.terminal_implementation_action = Proc.new { raise(*args) }
nil
end
@@ -177,6 +175,11 @@
def and_yield(*args, &block)
raise_already_invoked_error_if_necessary(__method__)
yield @eval_context = Object.new if block
+
+ # Initialize args to yield now that it's being used, see also: comment
+ # in constructor.
+ @args_to_yield ||= []
+
@args_to_yield << args
self.initial_implementation_action =
AndYieldImplementation.new(@args_to_yield, @eval_context, @error_generator)
self
@@ -248,7 +251,7 @@
# @example
# expect(car).to receive(:stop).never
def never
- ErrorGenerator.raise_double_negation_error("expect(obj)") if negative?
+ error_generator.raise_double_negation_error("expect(obj)") if negative?
@expected_received_count = 0
self
end
@@ -371,8 +374,10 @@
@expectation_type = type
@ordered = false
@at_least = @at_most = @exactly = nil
- @args_to_yield = []
- @failed_fast = nil
+
+ # Initialized to nil so that we don't allocate an array for every
+ # mock or stub. See also comment in `and_yield`.
+ @args_to_yield = nil
@eval_context = nil
@yield_receiver_to_implementation_block = false
@@ -426,9 +431,8 @@
end
def verify_messages_received
- InsertOntoBacktrace.line(@expected_from) do
- generate_error unless expected_messages_received? || failed_fast?
- end
+ return if expected_messages_received?
+ generate_error
end
def expected_messages_received?
@@ -464,14 +468,28 @@
similar_messages << args
end
+ def unadvise(args)
+ similar_messages.delete_if { |message| args.include?(message) }
+ end
+
def generate_error
if similar_messages.empty?
- @error_generator.raise_expectation_error(@message,
@expected_received_count, @argument_list_matcher, @actual_received_count,
expectation_count_type, *expected_args)
+ @error_generator.raise_expectation_error(
+ @message, @expected_received_count, @argument_list_matcher,
+ @actual_received_count, expectation_count_type, expected_args,
+ @expected_from, exception_source_id
+ )
else
- @error_generator.raise_similar_message_args_error(self,
*@similar_messages)
+ @error_generator.raise_similar_message_args_error(
+ self, @similar_messages, @expected_from
+ )
end
end
+ def raise_unexpected_message_args_error(args_for_multiple_calls)
+ @error_generator.raise_unexpected_message_args_error(self,
args_for_multiple_calls, exception_source_id)
+ end
+
def expectation_count_type
return :at_least if @at_least
return :at_most if @at_most
@@ -481,7 +499,7 @@
def description_for(verb)
@error_generator.describe_expectation(
verb, @message, @expected_received_count,
- @actual_received_count, *expected_args
+ @actual_received_count, expected_args
)
end
@@ -512,28 +530,33 @@
private
+ def exception_source_id
+ @exception_source_id ||= "#{self.class.name} #{__id__}"
+ end
+
def invoke_incrementing_actual_calls_by(increment, allowed_to_fail,
parent_stub, *args, &block)
args.unshift(orig_object) if yield_receiver_to_implementation_block?
if negative? || (allowed_to_fail && (@exactly || @at_most) &&
(@actual_received_count == @expected_received_count))
- @actual_received_count += increment
- @failed_fast = true
# args are the args we actually received, @argument_list_matcher
is the
# list of args we were expecting
- @error_generator.raise_expectation_error(@message,
@expected_received_count, @argument_list_matcher, @actual_received_count,
expectation_count_type, *args)
+ @error_generator.raise_expectation_error(
+ @message, @expected_received_count,
+ @argument_list_matcher,
+ @actual_received_count + increment,
+ expectation_count_type, args, nil, exception_source_id
+ )
end
@order_group.handle_order_constraint self
- begin
- if implementation.present?
- implementation.call(*args, &block)
- elsif parent_stub
- parent_stub.invoke(nil, *args, &block)
- end
- ensure
- @actual_received_count += increment
+ if implementation.present?
+ implementation.call(*args, &block)
+ elsif parent_stub
+ parent_stub.invoke(nil, *args, &block)
end
+ ensure
+ @actual_received_count += increment
end
def has_been_invoked?
@@ -543,15 +566,7 @@
def raise_already_invoked_error_if_necessary(calling_customization)
return unless has_been_invoked?
- error_message = "The message expectation for
#{orig_object.inspect}.#{message} has already been invoked " \
- "and cannot be modified further (e.g. using
`#{calling_customization}`). All message expectation " \
- "customizations must be applied before it is used for the first
time."
-
- raise MockExpectationAlreadyInvokedError, error_message
- end
-
- def failed_fast?
- @failed_fast
+ error_generator.raise_already_invoked_error(message,
calling_customization)
end
def set_expected_received_count(relativity, n)
@@ -698,17 +713,5 @@
"to call the original implementation, and cannot be modified
further."
end
end
-
- # Insert original locations into stacktraces
- #
- # @private
- class InsertOntoBacktrace
- def self.line(location)
- yield
- rescue RSpec::Mocks::MockExpectationError => error
- error.backtrace.insert(0, location)
- Kernel.raise error
- end
- end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/method_double.rb
new/lib/rspec/mocks/method_double.rb
--- old/lib/rspec/mocks/method_double.rb 2015-02-24 04:24:30.000000000
+0100
+++ new/lib/rspec/mocks/method_double.rb 2015-06-12 17:05:16.000000000
+0200
@@ -18,20 +18,24 @@
@stubs = []
end
- def original_method
+ def original_implementation_callable
# If original method is not present, uses the `method_missing`
# handler of the object. This accounts for cases where the user has not
# correctly defined `respond_to?`, and also 1.8 which does not provide
# method handles for missing methods even if `respond_to?` is correct.
- @original_method ||=
- @method_stasher.original_method ||
- @proxy.original_method_handle_for(method_name) ||
+ @original_implementation_callable ||= original_method ||
Proc.new do |*args, &block|
@object.__send__(:method_missing, @method_name, *args, &block)
end
end
- alias_method :save_original_method!, :original_method
+ alias_method :save_original_implementation_callable!,
:original_implementation_callable
+
+ def original_method
+ @original_method ||=
+ @method_stasher.original_method ||
+ @proxy.original_method_handle_for(method_name)
+ end
# @private
def visibility
@@ -45,7 +49,7 @@
# @private
def configure_method
- @original_visibility = [visibility, method_name]
+ @original_visibility = visibility
@method_stasher.stash unless @method_is_proxied
define_proxy_method
end
@@ -54,7 +58,7 @@
def define_proxy_method
return if @method_is_proxied
- save_original_method!
+ save_original_implementation_callable!
definition_target.class_exec(self, method_name, visibility) do
|method_double, method_name, visibility|
define_method(method_name) do |*args, &block|
method_double.proxy_method_invoked(self, *args, &block)
@@ -101,7 +105,7 @@
return unless @original_visibility &&
MethodReference.method_defined_at_any_visibility?(object_singleton_class,
@method_name)
- object_singleton_class.__send__(*@original_visibility)
+ object_singleton_class.__send__(@original_visibility, method_name)
end
# @private
@@ -198,7 +202,7 @@
# @private
def raise_method_not_stubbed_error
- raise MockExpectationError, "The method `#{method_name}` was not
stubbed or was already unstubbed"
+
RSpec::Mocks.error_generator.raise_method_not_stubbed_error(method_name)
end
# In Ruby 2.0.0 and above prepend will alter the method lookup chain.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/method_reference.rb
new/lib/rspec/mocks/method_reference.rb
--- old/lib/rspec/mocks/method_reference.rb 2015-02-24 04:24:30.000000000
+0100
+++ new/lib/rspec/mocks/method_reference.rb 2015-06-12 17:05:16.000000000
+0200
@@ -6,6 +6,10 @@
#
# @private
class MethodReference
+ def self.for(object_reference, method_name)
+ new(object_reference, method_name)
+ end
+
def initialize(object_reference, method_name)
@object_reference = object_reference
@method_name = method_name
@@ -133,6 +137,14 @@
# @private
class ObjectMethodReference < MethodReference
+ def self.for(object_reference, method_name)
+ if ClassNewMethodReference.applies_to?(method_name) {
object_reference.when_loaded { |o| o } }
+ ClassNewMethodReference.new(object_reference, method_name)
+ else
+ super
+ end
+ end
+
private
def method_implemented?(object)
@@ -151,5 +163,30 @@
MethodReference.method_visibility_for(object, @method_name)
end
end
+
+ # When a class's `.new` method is stubbed, we want to use the method
+ # signature from `#initialize` because `.new`'s signature is a generic
+ # `def new(*args)` and it simply delegates to `#initialize` and forwards
+ # all args...so the method with the actually used signature is
`#initialize`.
+ #
+ # This method reference implementation handles that specific case.
+ # @private
+ class ClassNewMethodReference < ObjectMethodReference
+ def self.applies_to?(method_name)
+ return false unless method_name == :new
+ klass = yield
+ return false unless klass.respond_to?(:new, true)
+
+ # We only want to apply our special logic to normal `new` methods.
+ # Methods that the user has monkeyed with should be left as-is.
+ klass.method(:new).owner == ::Class
+ end
+
+ def with_signature
+ @object_reference.when_loaded do |klass|
+ yield
Support::MethodSignature.new(klass.instance_method(:initialize))
+ end
+ end
+ end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/proxy.rb new/lib/rspec/mocks/proxy.rb
--- old/lib/rspec/mocks/proxy.rb 2015-02-24 04:24:30.000000000 +0100
+++ new/lib/rspec/mocks/proxy.rb 2015-06-12 17:05:16.000000000 +0200
@@ -14,11 +14,10 @@
end
# @private
- def initialize(object, order_group, name=nil, options={})
+ def initialize(object, order_group, options={})
@object = object
@order_group = order_group
- @name = name
- @error_generator = ErrorGenerator.new(object, name)
+ @error_generator = ErrorGenerator.new(object)
@messages_received = []
@options = options
@null_object = false
@@ -46,8 +45,10 @@
nil
end
+ DEFAULT_MESSAGE_EXPECTATION_OPTS = {}.freeze
+
# @private
- def add_message_expectation(method_name, opts={}, &block)
+ def add_message_expectation(method_name,
opts=DEFAULT_MESSAGE_EXPECTATION_OPTS, &block)
location = opts.fetch(:expected_from) {
CallerFilter.first_non_rspec_line }
meth_double = method_double_for(method_name)
@@ -98,11 +99,17 @@
# @private
def check_for_unexpected_arguments(expectation)
- @messages_received.each do |(method_name, args, _)|
- next unless expectation.matches_name_but_not_args(method_name, *args)
+ return if @messages_received.empty?
+
+ return if @messages_received.any? { |method_name, args, _|
expectation.matches?(method_name, *args) }
- raise_unexpected_message_args_error(expectation, *args)
+ name_but_not_args, others = @messages_received.partition do
|(method_name, args, _)|
+ expectation.matches_name_but_not_args(method_name, *args)
end
+
+ return if name_but_not_args.empty? && !others.empty?
+
+ expectation.raise_unexpected_message_args_error(name_but_not_args.map
{ |args| args[1] })
end
# @private
@@ -142,6 +149,11 @@
end
# @private
+ def messages_arg_list
+ @messages_received.map { |_, args, _| args }
+ end
+
+ # @private
def has_negative_expectation?(message)
method_double_for(message).expectations.find { |expectation|
expectation.negative_expectation_for?(message) }
end
@@ -166,16 +178,17 @@
end
stub.invoke(nil, *args, &block)
elsif expectation
+ expectation.unadvise(messages_arg_list)
expectation.invoke(stub, *args, &block)
elsif (expectation = find_almost_matching_expectation(message, *args))
expectation.advise(*args) if null_object? unless
expectation.expected_messages_received?
if null_object? || !has_negative_expectation?(message)
- raise_unexpected_message_args_error(expectation, *args)
+ expectation.raise_unexpected_message_args_error([args])
end
elsif (stub = find_almost_matching_stub(message, *args))
stub.advise(*args)
- raise_missing_default_stub_error(stub, *args)
+ raise_missing_default_stub_error(stub, [args])
elsif Class === @object
@object.superclass.__send__(message, *args, &block)
else
@@ -184,18 +197,13 @@
end
# @private
- def raise_unexpected_message_error(method_name, *args)
- @error_generator.raise_unexpected_message_error method_name, *args
- end
-
- # @private
- def raise_unexpected_message_args_error(expectation, *args)
- @error_generator.raise_unexpected_message_args_error(expectation,
*args)
+ def raise_unexpected_message_error(method_name, args)
+ @error_generator.raise_unexpected_message_error method_name, args
end
# @private
- def raise_missing_default_stub_error(expectation, *args)
- @error_generator.raise_missing_default_stub_error(expectation, *args)
+ def raise_missing_default_stub_error(expectation,
args_for_multiple_calls)
+ @error_generator.raise_missing_default_stub_error(expectation,
args_for_multiple_calls)
end
# @private
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/test_double.rb
new/lib/rspec/mocks/test_double.rb
--- old/lib/rspec/mocks/test_double.rb 2015-02-24 04:24:30.000000000 +0100
+++ new/lib/rspec/mocks/test_double.rb 2015-06-12 17:05:16.000000000 +0200
@@ -39,7 +39,7 @@
# @private
def inspect
- "#<#{self.class}:#{'0x%x' % object_id} @name=#{@name.inspect}>"
+ TestDoubleFormatter.format(self)
end
# @private
@@ -91,14 +91,14 @@
# https://github.com/jruby/jruby/issues/1398
visibility = proxy.visibility_for(message)
if visibility == :private || visibility == :protected
- ErrorGenerator.new(self, @name).raise_non_public_error(
+ ErrorGenerator.new(self).raise_non_public_error(
message, visibility
)
end
# Required wrapping doubles in an Array on Ruby 1.9.2
raise NoMethodError if [:to_a, :to_ary].include? message
- proxy.raise_unexpected_message_error(message, *args)
+ proxy.raise_unexpected_message_error(message, args)
end
def assign_stubs(stubs)
@@ -112,12 +112,12 @@
end
def __build_mock_proxy(order_group)
- TestDoubleProxy.new(self, order_group, @name)
+ TestDoubleProxy.new(self, order_group)
end
def __raise_expired_error
return false unless @__expired
- ErrorGenerator.new(self, @name).raise_expired_test_double_error
+ ErrorGenerator.new(self).raise_expired_test_double_error
end
def initialize_copy(other)
@@ -131,5 +131,40 @@
class Double
include TestDouble
end
+
+ # @private
+ module TestDoubleFormatter
+ def self.format(dbl, unwrap=false)
+ format = "#{type_desc(dbl)}#{verified_module_desc(dbl)}
#{name_desc(dbl)}"
+ return format if unwrap
+ "#<#{format}>"
+ end
+
+ class << self
+ private
+
+ def type_desc(dbl)
+ case dbl
+ when InstanceVerifyingDouble then "InstanceDouble"
+ when ClassVerifyingDouble then "ClassDouble"
+ when ObjectVerifyingDouble then "ObjectDouble"
+ else "Double"
+ end
+ end
+
+ # @private
+ IVAR_GET = Object.instance_method(:instance_variable_get)
+
+ def verified_module_desc(dbl)
+ return nil unless VerifyingDouble === dbl
+ "(#{IVAR_GET.bind(dbl).call(:@doubled_module).description})"
+ end
+
+ def name_desc(dbl)
+ return "(anonymous)" unless (name = IVAR_GET.bind(dbl).call(:@name))
+ name.inspect
+ end
+ end
+ end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/verifying_double.rb
new/lib/rspec/mocks/verifying_double.rb
--- old/lib/rspec/mocks/verifying_double.rb 2015-02-24 04:24:30.000000000
+0100
+++ new/lib/rspec/mocks/verifying_double.rb 2015-06-12 17:05:16.000000000
+0200
@@ -1,5 +1,4 @@
RSpec::Support.require_rspec_mocks 'verifying_proxy'
-require 'stringio'
module RSpec
module Mocks
@@ -35,8 +34,16 @@
super
end
+ # @private
+ module SilentIO
+ def self.method_missing(*); end
+ def self.respond_to?(*)
+ true
+ end
+ end
+
# Redefining `__send__` causes ruby to issue a warning.
- old, $stderr = $stderr, StringIO.new
+ old, $stderr = $stderr, SilentIO
def __send__(name, *args, &block)
@__sending_message = name
super
@@ -55,8 +62,6 @@
possible_name = args.first
name = if String === possible_name || Symbol === possible_name
args.shift
- else
- @description
end
super(name, *args)
@@ -73,13 +78,8 @@
include TestDouble
include VerifyingDouble
- def initialize(doubled_module, *args)
- @description = "#{doubled_module.description} (instance)"
- super
- end
-
def __build_mock_proxy(order_group)
- VerifyingProxy.new(self, order_group, @name,
+ VerifyingProxy.new(self, order_group,
@doubled_module,
InstanceMethodReference
)
@@ -101,13 +101,8 @@
private
- def initialize(doubled_module, *args)
- @description = doubled_module.description
- super
- end
-
def __build_mock_proxy(order_group)
- VerifyingProxy.new(self, order_group, @name,
+ VerifyingProxy.new(self, order_group,
@doubled_module,
ObjectMethodReference
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/verifying_proxy.rb
new/lib/rspec/mocks/verifying_proxy.rb
--- old/lib/rspec/mocks/verifying_proxy.rb 2015-02-24 04:24:30.000000000
+0100
+++ new/lib/rspec/mocks/verifying_proxy.rb 2015-06-12 17:05:16.000000000
+0200
@@ -25,7 +25,8 @@
@error_generator.raise_unimplemented_error(
@doubled_module,
- method_name
+ method_name,
+ @object
)
end
@@ -55,8 +56,8 @@
class VerifyingProxy < TestDoubleProxy
include VerifyingProxyMethods
- def initialize(object, order_group, name, doubled_module,
method_reference_class)
- super(object, order_group, name)
+ def initialize(object, order_group, doubled_module,
method_reference_class)
+ super(object, order_group)
@object = object
@doubled_module = doubled_module
@method_reference_class = method_reference_class
@@ -71,7 +72,7 @@
def method_reference
@method_reference ||= Hash.new do |h, k|
- h[k] = @method_reference_class.new(@doubled_module, k)
+ h[k] = @method_reference_class.for(@doubled_module, k)
end
end
@@ -95,7 +96,11 @@
# A custom method double is required to pass through a way to lookup
# methods to determine their parameters.
@method_doubles = Hash.new do |h, k|
- h[k] = VerifyingExistingMethodDouble.new(object, k, self)
+ h[k] = VerifyingExistingMethodDouble.for(object, k, self)
+ end
+
+ RSpec::Mocks.configuration.verifying_double_callbacks.each do |block|
+ block.call @doubled_module
end
end
@@ -158,16 +163,35 @@
# 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!
+ save_original_implementation_callable!
end
def with_signature
- yield Support::MethodSignature.new(original_method)
+ yield Support::MethodSignature.new(original_implementation_callable)
end
def unimplemented?
!@valid_method
end
+
+ def self.for(object, method_name, proxy)
+ if ClassNewMethodReference.applies_to?(method_name) { object }
+ VerifyingExistingClassNewMethodDouble
+ else
+ self
+ end.new(object, method_name, proxy)
+ end
+ end
+
+ # Used in place of a `VerifyingExistingMethodDouble` for the specific case
+ # of mocking or stubbing a `new` method on a class. In this case, we
substitute
+ # the method signature from `#initialize` since new's signature is just
`*args`.
+ #
+ # @private
+ class VerifyingExistingClassNewMethodDouble < VerifyingExistingMethodDouble
+ def with_signature
+ yield Support::MethodSignature.new(object.instance_method(:initialize))
+ end
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/rspec/mocks/version.rb
new/lib/rspec/mocks/version.rb
--- old/lib/rspec/mocks/version.rb 2015-02-24 04:24:30.000000000 +0100
+++ new/lib/rspec/mocks/version.rb 2015-06-12 17:05:16.000000000 +0200
@@ -3,7 +3,7 @@
# Version information for RSpec mocks.
module Version
# Version of RSpec mocks currently in use in SemVer format.
- STRING = '3.2.1'
+ STRING = '3.3.0'
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata 2015-02-24 04:24:29.000000000 +0100
+++ new/metadata 2015-06-12 17:05:16.000000000 +0200
@@ -1,7 +1,7 @@
--- !ruby/object:Gem::Specification
name: rspec-mocks
version: !ruby/object:Gem::Version
- version: 3.2.1
+ version: 3.3.0
platform: ruby
authors:
- Steven Baker
@@ -45,7 +45,7 @@
ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
F3MdtaDehhjC
-----END CERTIFICATE-----
-date: 2015-02-24 00:00:00.000000000 Z
+date: 2015-06-12 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: rspec-support
@@ -53,14 +53,14 @@
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: 3.2.0
+ version: 3.3.0
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: 3.2.0
+ version: 3.3.0
- !ruby/object:Gem::Dependency
name: diff-lcs
requirement: !ruby/object:Gem::Requirement
@@ -151,6 +151,7 @@
- lib/rspec/mocks.rb
- lib/rspec/mocks/any_instance.rb
- lib/rspec/mocks/any_instance/chain.rb
+- lib/rspec/mocks/any_instance/error_generator.rb
- lib/rspec/mocks/any_instance/expect_chain_chain.rb
- lib/rspec/mocks/any_instance/expectation_chain.rb
- lib/rspec/mocks/any_instance/message_chains.rb
@@ -207,10 +208,10 @@
- !ruby/object:Gem::Version
version: '0'
requirements: []
-rubyforge_project: rspec
-rubygems_version: 2.4.5
+rubyforge_project:
+rubygems_version: 2.2.2
signing_key:
specification_version: 4
-summary: rspec-mocks-3.2.1
+summary: rspec-mocks-3.3.0
test_files: []
has_rdoc:
Files old/metadata.gz.sig and new/metadata.gz.sig differ