rspec-mocks 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +47 -0
- data/README.md +2 -2
- data/lib/rspec/mocks/any_instance.rb +1 -0
- data/lib/rspec/mocks/any_instance/chain.rb +1 -1
- data/lib/rspec/mocks/any_instance/error_generator.rb +31 -0
- data/lib/rspec/mocks/any_instance/message_chains.rb +1 -3
- data/lib/rspec/mocks/any_instance/recorder.rb +7 -10
- data/lib/rspec/mocks/argument_list_matcher.rb +3 -3
- data/lib/rspec/mocks/configuration.rb +6 -5
- data/lib/rspec/mocks/error_generator.rb +163 -111
- data/lib/rspec/mocks/example_methods.rb +2 -5
- data/lib/rspec/mocks/matchers/have_received.rb +6 -9
- data/lib/rspec/mocks/message_chain.rb +0 -4
- data/lib/rspec/mocks/message_expectation.rb +56 -53
- data/lib/rspec/mocks/method_double.rb +13 -9
- data/lib/rspec/mocks/method_reference.rb +37 -0
- data/lib/rspec/mocks/proxy.rb +26 -18
- data/lib/rspec/mocks/test_double.rb +40 -5
- data/lib/rspec/mocks/verifying_double.rb +11 -16
- data/lib/rspec/mocks/verifying_proxy.rb +31 -7
- data/lib/rspec/mocks/version.rb +1 -1
- metadata +8 -7
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bb4586d03e4b2bf84d904af032165dfae270599
|
4
|
+
data.tar.gz: 6889f7727cf4545a05618a19c0f7ff35174718ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bb9e03448dfde3e78aec7388dd7b49bccb8005ec49a7ab525b41818a6678e41568fa7946a4d443a8103058d77c4ae2760ac07eb69b0ef37dd39f197e580aa48
|
7
|
+
data.tar.gz: 00a6e20fb91ccb3dd7212ac5877e9b348609aede07ed8158aee6032f1e30d7d89a833a7d1107343e780da15daa0800d94985cdd151796434f5413c8663935fa0
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,3 +1,50 @@
|
|
1
|
+
### 3.3.0 / 2015-06-12
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.1...v3.3.0)
|
3
|
+
|
4
|
+
Enhancements:
|
5
|
+
|
6
|
+
* When stubbing `new` on `MyClass` or `class_double(MyClass)`, use the
|
7
|
+
method signature from `MyClass#initialize` to verify arguments.
|
8
|
+
(Myron Marston, #886)
|
9
|
+
* Use matcher descriptions when generating description of received arguments
|
10
|
+
for mock expectation failures. (Tim Wade, #891)
|
11
|
+
* Avoid loading `stringio` unnecessarily. (Myron Marston, #894)
|
12
|
+
* Verifying doubles failure messages now distinguish between class and instance
|
13
|
+
level methods. (Tim Wade, #896, #908)
|
14
|
+
* Improve mock expectation failure messages so that it combines both
|
15
|
+
number of times and the received arguments in the output. (John Ceh, #918)
|
16
|
+
* Improve how test doubles are represented in failure messages.
|
17
|
+
(Siva Gollapalli, Myron Marston, #932)
|
18
|
+
* Rename `RSpec::Mocks::Configuration#when_declaring_verifying_double` to
|
19
|
+
`RSpec::Mocks::Configuration#before_verifying_doubles` and utilise when
|
20
|
+
verifying partial doubles. (Jon Rowe, #940)
|
21
|
+
* Use rspec-support's `ObjectFormatter` for improved formatting of
|
22
|
+
arguments in failure messages so that, for example, full time
|
23
|
+
precisions is displayed for time objects. (Gavin Miller, Myron Marston, #955)
|
24
|
+
|
25
|
+
Bug Fixes:
|
26
|
+
|
27
|
+
* Ensure expectations that raise eagerly also raise during RSpec verification.
|
28
|
+
This means that if exceptions are caught inside test execution the test will
|
29
|
+
still fail. (Sam Phippen, #884)
|
30
|
+
* Fix `have_received(msg).with(args).exactly(n).times` and
|
31
|
+
`receive(msg).with(args).exactly(n).times` failure messages
|
32
|
+
for when the message was received the wrong number of times with
|
33
|
+
the specified args, and also received additional times with other
|
34
|
+
arguments. Previously it confusingly listed the arguments as being
|
35
|
+
mis-matched (even when the double was allowed to receive with any
|
36
|
+
args) rather than listing the count. (John Ceh, #918)
|
37
|
+
* Fix `any_args`/`anything` support so that we avoid calling `obj == anything`
|
38
|
+
on user objects that may have improperly implemented `==` in a way that
|
39
|
+
raises errors. (Myron Marston, #924)
|
40
|
+
* Fix edge case involving stubbing the same method on a class and a subclass
|
41
|
+
which previously hit a `NoMethodError` internally in RSpec. (Myron Marston #954)
|
42
|
+
* Fix edge case where the message received count would be incremented multiple
|
43
|
+
times for one failure. (Myron Marston, #957)
|
44
|
+
* Fix failure messages for when spies received the expected message with
|
45
|
+
different arguments and also received another message. (Maurício Linhares, #960)
|
46
|
+
* Silence whitespace-only diffs. (Myron Marston, #969)
|
47
|
+
|
1
48
|
### 3.2.1 / 2015-02-23
|
2
49
|
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.0...v3.2.1)
|
3
50
|
|
data/README.md
CHANGED
@@ -417,8 +417,8 @@ There are many different viewpoints about the meaning of mocks and stubs. If
|
|
417
417
|
you are interested in learning more, here is some recommended reading:
|
418
418
|
|
419
419
|
* Mock Objects: http://www.mockobjects.com/
|
420
|
-
* Endo-Testing: http://
|
421
|
-
* Mock Roles, Not Objects: http://jmock.org/oopsla2004.pdf
|
420
|
+
* Endo-Testing: http://www.ccs.neu.edu/research/demeter/related-work/extreme-programming/MockObjectsFinal.PDF
|
421
|
+
* Mock Roles, Not Objects: http://www.jmock.org/oopsla2004.pdf
|
422
422
|
* Test Double: http://www.martinfowler.com/bliki/TestDouble.html
|
423
423
|
* Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html
|
424
424
|
* Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Mocks
|
3
|
+
module AnyInstance
|
4
|
+
# @private
|
5
|
+
class ErrorGenerator < ::RSpec::Mocks::ErrorGenerator
|
6
|
+
def raise_second_instance_received_message_error(unfulfilled_expectations)
|
7
|
+
__raise "Exactly one instance should have received the following " \
|
8
|
+
"message(s) but didn't: #{unfulfilled_expectations.sort.join(', ')}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def raise_does_not_implement_error(klass, method_name)
|
12
|
+
__raise "#{klass} does not implement ##{method_name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def raise_message_already_received_by_other_instance_error(method_name, object_inspect, invoked_instance)
|
16
|
+
__raise "The message '#{method_name}' was received by #{object_inspect} " \
|
17
|
+
"but has already been received by #{invoked_instance}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def raise_not_supported_with_prepend_error(method_name, problem_mod)
|
21
|
+
__raise "Using `any_instance` to stub a method (#{method_name}) that has been " \
|
22
|
+
"defined on a prepended module (#{problem_mod}) is not supported."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.error_generator
|
27
|
+
@error_generator ||= ErrorGenerator.new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -75,9 +75,7 @@ module RSpec
|
|
75
75
|
return unless ExpectationChain === instance
|
76
76
|
return if @instance_with_expectation.equal?(instance)
|
77
77
|
|
78
|
-
|
79
|
-
"Exactly one instance should have received the following " \
|
80
|
-
"message(s) but didn't: #{unfulfilled_expectations.sort.join(', ')}"
|
78
|
+
AnyInstance.error_generator.raise_second_instance_received_message_error(unfulfilled_expectations)
|
81
79
|
end
|
82
80
|
end
|
83
81
|
end
|
@@ -76,7 +76,7 @@ module RSpec
|
|
76
76
|
# @see Methods#unstub
|
77
77
|
def unstub(method_name)
|
78
78
|
unless @observed_methods.include?(method_name.to_sym)
|
79
|
-
|
79
|
+
AnyInstance.error_generator.raise_method_not_stubbed_error(method_name)
|
80
80
|
end
|
81
81
|
message_chains.remove_stub_chains_for!(method_name)
|
82
82
|
stubs[method_name].clear
|
@@ -91,9 +91,7 @@ module RSpec
|
|
91
91
|
return unless @expectation_set
|
92
92
|
return if message_chains.all_expectations_fulfilled?
|
93
93
|
|
94
|
-
|
95
|
-
"Exactly one instance should have received the following " \
|
96
|
-
"message(s) but didn't: #{message_chains.unfulfilled_expectations.sort.join(', ')}"
|
94
|
+
AnyInstance.error_generator.raise_second_instance_received_message_error(message_chains.unfulfilled_expectations)
|
97
95
|
end
|
98
96
|
|
99
97
|
# @private
|
@@ -221,8 +219,7 @@ module RSpec
|
|
221
219
|
|
222
220
|
if RSpec::Mocks.configuration.verify_partial_doubles?
|
223
221
|
unless public_protected_or_private_method_defined?(method_name)
|
224
|
-
|
225
|
-
"#{@klass} does not implement ##{method_name}"
|
222
|
+
AnyInstance.error_generator.raise_does_not_implement_error(@klass, method_name)
|
226
223
|
end
|
227
224
|
end
|
228
225
|
|
@@ -242,7 +239,9 @@ module RSpec
|
|
242
239
|
@klass.__send__(:define_method, method_name) do |*_args, &_blk|
|
243
240
|
invoked_instance = recorder.instance_that_received(method_name)
|
244
241
|
inspect = "#<#{self.class}:#{object_id} #{instance_variables.map { |name| "#{name}=#{instance_variable_get name}" }.join(', ')}>"
|
245
|
-
|
242
|
+
AnyInstance.error_generator.raise_message_already_received_by_other_instance_error(
|
243
|
+
method_name, inspect, invoked_instance
|
244
|
+
)
|
246
245
|
end
|
247
246
|
end
|
248
247
|
|
@@ -252,9 +251,7 @@ module RSpec
|
|
252
251
|
problem_mod = prepended_modules.find { |mod| mod.method_defined?(method_name) }
|
253
252
|
return unless problem_mod
|
254
253
|
|
255
|
-
|
256
|
-
"Using `any_instance` to stub a method (#{method_name}) that has been " \
|
257
|
-
"defined on a prepended module (#{problem_mod}) is not supported."
|
254
|
+
AnyInstance.error_generator.raise_not_supported_with_prepend_error(method_name, problem_mod)
|
258
255
|
end
|
259
256
|
else
|
260
257
|
def allow_no_prepended_module_definition_of(_method_name)
|
@@ -64,7 +64,7 @@ module RSpec
|
|
64
64
|
def resolve_expected_args_based_on(actual_args)
|
65
65
|
return [] if [ArgumentMatchers::NoArgsMatcher::INSTANCE] == expected_args
|
66
66
|
|
67
|
-
any_args_index = expected_args.index
|
67
|
+
any_args_index = expected_args.index { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a }
|
68
68
|
return expected_args unless any_args_index
|
69
69
|
|
70
70
|
replace_any_args_with_splat_of_anything(any_args_index, actual_args.count)
|
@@ -81,10 +81,10 @@ module RSpec
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def ensure_expected_args_valid!
|
84
|
-
if expected_args.count
|
84
|
+
if expected_args.count { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a } > 1
|
85
85
|
raise ArgumentError, "`any_args` can only be passed to " \
|
86
86
|
"`with` once but you have passed it multiple times."
|
87
|
-
elsif expected_args.count > 1 && expected_args.
|
87
|
+
elsif expected_args.count > 1 && expected_args.any? { |a| ArgumentMatchers::NoArgsMatcher::INSTANCE == a }
|
88
88
|
raise ArgumentError, "`no_args` can only be passed as a " \
|
89
89
|
"singleton argument to `with` (i.e. `with(no_args)`), " \
|
90
90
|
"but you have passed additional arguments."
|
@@ -103,17 +103,18 @@ module RSpec
|
|
103
103
|
# Provides a way to perform customisations when verifying doubles.
|
104
104
|
#
|
105
105
|
# @example
|
106
|
-
# RSpec::Mocks.configuration.
|
106
|
+
# RSpec::Mocks.configuration.before_verifying_doubles do |ref|
|
107
107
|
# ref.some_method!
|
108
108
|
# end
|
109
|
-
def
|
110
|
-
|
109
|
+
def before_verifying_doubles(&block)
|
110
|
+
verifying_double_callbacks << block
|
111
111
|
end
|
112
|
+
alias :when_declaring_verifying_double :before_verifying_doubles
|
112
113
|
|
113
114
|
# @api private
|
114
115
|
# Returns an array of blocks to call when verifying doubles
|
115
|
-
def
|
116
|
-
@
|
116
|
+
def verifying_double_callbacks
|
117
|
+
@verifying_double_callbacks ||= []
|
117
118
|
end
|
118
119
|
|
119
120
|
def transfer_nested_constants?
|
@@ -1,4 +1,4 @@
|
|
1
|
-
RSpec::Support.require_rspec_support
|
1
|
+
RSpec::Support.require_rspec_support "object_formatter"
|
2
2
|
|
3
3
|
module RSpec
|
4
4
|
module Mocks
|
@@ -36,9 +36,8 @@ module RSpec
|
|
36
36
|
class ErrorGenerator
|
37
37
|
attr_writer :opts
|
38
38
|
|
39
|
-
def initialize(target
|
39
|
+
def initialize(target=nil)
|
40
40
|
@target = target
|
41
|
-
@name = name
|
42
41
|
end
|
43
42
|
|
44
43
|
# @private
|
@@ -47,41 +46,26 @@ module RSpec
|
|
47
46
|
end
|
48
47
|
|
49
48
|
# @private
|
50
|
-
def raise_unexpected_message_error(message,
|
51
|
-
__raise "#{intro} received unexpected message :#{message}#{
|
49
|
+
def raise_unexpected_message_error(message, args)
|
50
|
+
__raise "#{intro} received unexpected message :#{message} with #{format_args(args)}"
|
52
51
|
end
|
53
52
|
|
54
53
|
# @private
|
55
|
-
def raise_unexpected_message_args_error(expectation,
|
56
|
-
|
57
|
-
actual_args = format_received_args(*args)
|
58
|
-
diff = diff_message(expectation.expected_args, args)
|
59
|
-
|
60
|
-
message = default_error_message(expectation, expected_args, actual_args)
|
61
|
-
message << "\nDiff:#{diff}" unless diff.empty?
|
62
|
-
|
63
|
-
__raise message
|
54
|
+
def raise_unexpected_message_args_error(expectation, args_for_multiple_calls, source_id=nil)
|
55
|
+
__raise error_message(expectation, args_for_multiple_calls), nil, source_id
|
64
56
|
end
|
65
57
|
|
66
58
|
# @private
|
67
|
-
def raise_missing_default_stub_error(expectation,
|
68
|
-
|
69
|
-
actual_args = format_received_args(*args)
|
70
|
-
diff = diff_message(expectation.expected_args, args)
|
71
|
-
|
72
|
-
message = default_error_message(expectation, expected_args, actual_args)
|
73
|
-
message << "\nDiff:\n #{diff}" unless diff.empty?
|
59
|
+
def raise_missing_default_stub_error(expectation, args_for_multiple_calls)
|
60
|
+
message = error_message(expectation, args_for_multiple_calls)
|
74
61
|
message << "\n Please stub a default value first if message might be received with other args as well. \n"
|
75
62
|
|
76
63
|
__raise message
|
77
64
|
end
|
78
65
|
|
79
66
|
# @private
|
80
|
-
def raise_similar_message_args_error(expectation,
|
81
|
-
|
82
|
-
actual_args = args_for_multiple_calls.map { |a| format_received_args(*a) }.join(", ")
|
83
|
-
|
84
|
-
__raise(default_error_message(expectation, expected_args, actual_args))
|
67
|
+
def raise_similar_message_args_error(expectation, args_for_multiple_calls, backtrace_line=nil)
|
68
|
+
__raise error_message(expectation, args_for_multiple_calls), backtrace_line
|
85
69
|
end
|
86
70
|
|
87
71
|
def default_error_message(expectation, expected_args, actual_args)
|
@@ -95,19 +79,37 @@ module RSpec
|
|
95
79
|
|
96
80
|
# rubocop:disable Style/ParameterLists
|
97
81
|
# @private
|
98
|
-
def raise_expectation_error(message, expected_received_count, argument_list_matcher,
|
82
|
+
def raise_expectation_error(message, expected_received_count, argument_list_matcher,
|
83
|
+
actual_received_count, expectation_count_type, args,
|
84
|
+
backtrace_line=nil, source_id=nil)
|
99
85
|
expected_part = expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher)
|
100
|
-
received_part = received_part_of_expectation_error(actual_received_count,
|
101
|
-
__raise "(#{intro}).#{message}#{format_args(
|
86
|
+
received_part = received_part_of_expectation_error(actual_received_count, args)
|
87
|
+
__raise "(#{intro(:unwrapped)}).#{message}#{format_args(args)}\n #{expected_part}\n #{received_part}", backtrace_line, source_id
|
102
88
|
end
|
103
89
|
# rubocop:enable Style/ParameterLists
|
104
90
|
|
105
91
|
# @private
|
106
|
-
def raise_unimplemented_error(doubled_module, method_name)
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
92
|
+
def raise_unimplemented_error(doubled_module, method_name, object)
|
93
|
+
message = case object
|
94
|
+
when InstanceVerifyingDouble
|
95
|
+
"the %s class does not implement the instance method: %s" <<
|
96
|
+
if ObjectMethodReference.for(doubled_module, method_name).implemented?
|
97
|
+
". Perhaps you meant to use `class_double` instead?"
|
98
|
+
else
|
99
|
+
""
|
100
|
+
end
|
101
|
+
when ClassVerifyingDouble
|
102
|
+
"the %s class does not implement the class method: %s" <<
|
103
|
+
if InstanceMethodReference.for(doubled_module, method_name).implemented?
|
104
|
+
". Perhaps you meant to use `instance_double` instead?"
|
105
|
+
else
|
106
|
+
""
|
107
|
+
end
|
108
|
+
else
|
109
|
+
"%s does not implement: %s"
|
110
|
+
end
|
111
|
+
|
112
|
+
__raise message % [doubled_module.description, method_name]
|
111
113
|
end
|
112
114
|
|
113
115
|
# @private
|
@@ -132,101 +134,131 @@ module RSpec
|
|
132
134
|
end
|
133
135
|
|
134
136
|
# @private
|
135
|
-
def
|
136
|
-
"
|
137
|
-
actual_method_call_args_description(actual_received_count, args)
|
137
|
+
def describe_expectation(verb, message, expected_received_count, _actual_received_count, args)
|
138
|
+
"#{verb} #{message}#{format_args(args)} #{count_message(expected_received_count)}"
|
138
139
|
end
|
139
140
|
|
140
141
|
# @private
|
141
|
-
def
|
142
|
-
"
|
143
|
-
expected_method_call_args_description(argument_list_matcher.expected_args)
|
142
|
+
def raise_out_of_order_error(message)
|
143
|
+
__raise "#{intro} received :#{message} out of order"
|
144
144
|
end
|
145
145
|
|
146
146
|
# @private
|
147
|
-
def
|
148
|
-
|
149
|
-
if count > 0 && args.length > 0
|
150
|
-
" with arguments: #{args.inspect.gsub(/\A\[(.+)\]\z/, '(\1)')}"
|
151
|
-
else
|
152
|
-
""
|
153
|
-
end
|
147
|
+
def raise_missing_block_error(args_to_yield)
|
148
|
+
__raise "#{intro} asked to yield |#{arg_list(args_to_yield)}| but no block was passed"
|
154
149
|
end
|
155
150
|
|
156
151
|
# @private
|
157
|
-
def
|
158
|
-
|
159
|
-
if args.length > 0
|
160
|
-
" with arguments: #{format_args(*args)}"
|
161
|
-
else
|
162
|
-
""
|
163
|
-
end
|
152
|
+
def raise_wrong_arity_error(args_to_yield, signature)
|
153
|
+
__raise "#{intro} yielded |#{arg_list(args_to_yield)}| to block with #{signature.description}"
|
164
154
|
end
|
165
155
|
|
166
156
|
# @private
|
167
|
-
def
|
168
|
-
|
169
|
-
|
170
|
-
when ArgumentMatchers::NoArgsMatcher then " with no arguments"
|
171
|
-
end
|
157
|
+
def raise_only_valid_on_a_partial_double(method)
|
158
|
+
__raise "#{intro} is a pure test double. `#{method}` is only " \
|
159
|
+
"available on a partial double."
|
172
160
|
end
|
173
161
|
|
174
162
|
# @private
|
175
|
-
def
|
176
|
-
"#{
|
163
|
+
def raise_expectation_on_unstubbed_method(method)
|
164
|
+
__raise "#{intro} expected to have received #{method}, but that " \
|
165
|
+
"object is not a spy or method has not been stubbed."
|
177
166
|
end
|
178
167
|
|
179
168
|
# @private
|
180
|
-
def
|
181
|
-
__raise "#{intro} received
|
169
|
+
def raise_expectation_on_mocked_method(method)
|
170
|
+
__raise "#{intro} expected to have received #{method}, but that " \
|
171
|
+
"method has been mocked instead of stubbed or spied."
|
182
172
|
end
|
183
173
|
|
184
174
|
# @private
|
185
|
-
def
|
186
|
-
__raise "
|
175
|
+
def raise_double_negation_error(wrapped_expression)
|
176
|
+
__raise "Isn't life confusing enough? You've already set a " \
|
177
|
+
"negative message expectation and now you are trying to " \
|
178
|
+
"negate it again with `never`. What does an expression like " \
|
179
|
+
"`#{wrapped_expression}.not_to receive(:msg).never` even mean?"
|
187
180
|
end
|
188
181
|
|
189
182
|
# @private
|
190
|
-
def
|
191
|
-
|
183
|
+
def raise_verifying_double_not_defined_error(ref)
|
184
|
+
notify(VerifyingDoubleNotDefinedError.new(
|
185
|
+
"#{ref.description.inspect} is not a defined constant. " \
|
186
|
+
"Perhaps you misspelt it? " \
|
187
|
+
"Disable check with `verify_doubled_constant_names` configuration option."
|
188
|
+
))
|
192
189
|
end
|
193
190
|
|
194
191
|
# @private
|
195
|
-
def
|
196
|
-
__raise "#{
|
192
|
+
def raise_have_received_disallowed(type, reason)
|
193
|
+
__raise "Using #{type}(...) with the `have_received` " \
|
194
|
+
"matcher is not supported#{reason}."
|
197
195
|
end
|
198
196
|
|
199
197
|
# @private
|
200
|
-
def
|
201
|
-
__raise "
|
202
|
-
"available on a partial double."
|
198
|
+
def raise_cant_constrain_count_for_negated_have_received_error(count_constraint)
|
199
|
+
__raise "can't use #{count_constraint} when negative"
|
203
200
|
end
|
204
201
|
|
205
202
|
# @private
|
206
|
-
def
|
207
|
-
__raise "
|
208
|
-
"object is not a spy or method has not been stubbed."
|
203
|
+
def raise_method_not_stubbed_error(method_name)
|
204
|
+
__raise "The method `#{method_name}` was not stubbed or was already unstubbed"
|
209
205
|
end
|
210
206
|
|
211
207
|
# @private
|
212
|
-
def
|
213
|
-
|
214
|
-
|
215
|
-
|
208
|
+
def raise_already_invoked_error(message, calling_customization)
|
209
|
+
error_message = "The message expectation for #{intro}.#{message} has already been invoked " \
|
210
|
+
"and cannot be modified further (e.g. using `#{calling_customization}`). All message expectation " \
|
211
|
+
"customizations must be applied before it is used for the first time."
|
216
212
|
|
217
|
-
|
218
|
-
raise "Isn't life confusing enough? You've already set a " \
|
219
|
-
"negative message expectation and now you are trying to " \
|
220
|
-
"negate it again with `never`. What does an expression like " \
|
221
|
-
"`#{wrapped_expression}.not_to receive(:msg).never` even mean?"
|
213
|
+
notify MockExpectationAlreadyInvokedError.new(error_message)
|
222
214
|
end
|
223
215
|
|
224
216
|
private
|
225
217
|
|
218
|
+
def received_part_of_expectation_error(actual_received_count, args)
|
219
|
+
"received: #{count_message(actual_received_count)}" +
|
220
|
+
method_call_args_description(args) do
|
221
|
+
actual_received_count > 0 && args.length > 0
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher)
|
226
|
+
"expected: #{count_message(expected_received_count, expectation_count_type)}" +
|
227
|
+
method_call_args_description(argument_list_matcher.expected_args) do
|
228
|
+
argument_list_matcher.expected_args.length > 0
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def method_call_args_description(args)
|
233
|
+
case args.first
|
234
|
+
when ArgumentMatchers::AnyArgsMatcher then " with any arguments"
|
235
|
+
when ArgumentMatchers::NoArgsMatcher then " with no arguments"
|
236
|
+
else
|
237
|
+
if yield
|
238
|
+
" with arguments: #{format_args(args)}"
|
239
|
+
else
|
240
|
+
""
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
226
245
|
def unexpected_arguments_message(expected_args_string, actual_args_string)
|
227
246
|
"with unexpected arguments\n expected: #{expected_args_string}\n got: #{actual_args_string}"
|
228
247
|
end
|
229
248
|
|
249
|
+
def error_message(expectation, args_for_multiple_calls)
|
250
|
+
expected_args = format_args(expectation.expected_args)
|
251
|
+
actual_args = format_received_args(args_for_multiple_calls)
|
252
|
+
message = default_error_message(expectation, expected_args, actual_args)
|
253
|
+
|
254
|
+
if args_for_multiple_calls.one?
|
255
|
+
diff = diff_message(expectation.expected_args, args_for_multiple_calls.first)
|
256
|
+
message << "\nDiff:#{diff}" unless diff.strip.empty?
|
257
|
+
end
|
258
|
+
|
259
|
+
message
|
260
|
+
end
|
261
|
+
|
230
262
|
def diff_message(expected_args, actual_args)
|
231
263
|
formatted_expected_args = expected_args.map do |x|
|
232
264
|
RSpec::Support.rspec_description_for_object(x)
|
@@ -253,47 +285,54 @@ module RSpec
|
|
253
285
|
RSpec::Support::Differ.new(:color => RSpec::Mocks.configuration.color?)
|
254
286
|
end
|
255
287
|
|
256
|
-
def intro
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
"
|
261
|
-
|
262
|
-
"
|
263
|
-
|
264
|
-
|
265
|
-
else
|
266
|
-
"nil"
|
288
|
+
def intro(unwrapped=false)
|
289
|
+
case @target
|
290
|
+
when TestDouble then TestDoubleFormatter.format(@target, unwrapped)
|
291
|
+
when Class then
|
292
|
+
formatted = "#{@target.inspect} (class)"
|
293
|
+
return formatted if unwrapped
|
294
|
+
"#<#{formatted}>"
|
295
|
+
when NilClass then "nil"
|
296
|
+
else @target
|
267
297
|
end
|
268
298
|
end
|
269
299
|
|
270
|
-
def __raise(message)
|
300
|
+
def __raise(message, backtrace_line=nil, source_id=nil)
|
271
301
|
message = opts[:message] unless opts[:message].nil?
|
272
|
-
|
302
|
+
exception = RSpec::Mocks::MockExpectationError.new(message)
|
303
|
+
prepend_to_backtrace(exception, backtrace_line) if backtrace_line
|
304
|
+
notify exception, :source_id => source_id
|
273
305
|
end
|
274
306
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
307
|
+
if RSpec::Support::Ruby.jruby?
|
308
|
+
def prepend_to_backtrace(exception, line)
|
309
|
+
raise exception
|
310
|
+
rescue RSpec::Mocks::MockExpectationError => with_backtrace
|
311
|
+
with_backtrace.backtrace.unshift(line)
|
312
|
+
end
|
313
|
+
else
|
314
|
+
def prepend_to_backtrace(exception, line)
|
315
|
+
exception.set_backtrace(caller.unshift line)
|
316
|
+
end
|
281
317
|
end
|
282
318
|
|
283
|
-
def
|
284
|
-
|
319
|
+
def notify(*args)
|
320
|
+
RSpec::Support.notify_failure(*args)
|
285
321
|
end
|
286
322
|
|
287
|
-
def
|
288
|
-
|
323
|
+
def format_args(args)
|
324
|
+
return "(no args)" if args.empty?
|
325
|
+
"(#{arg_list(args)})"
|
289
326
|
end
|
290
327
|
|
291
|
-
def
|
292
|
-
args.
|
328
|
+
def arg_list(args)
|
329
|
+
args.map { |arg| RSpec::Support::ObjectFormatter.format(arg) }.join(", ")
|
293
330
|
end
|
294
331
|
|
295
|
-
def
|
296
|
-
|
332
|
+
def format_received_args(args_for_multiple_calls)
|
333
|
+
grouped_args(args_for_multiple_calls).map do |args_for_one_call, index|
|
334
|
+
"#{format_args(args_for_one_call)}#{group_count(index, args_for_multiple_calls)}"
|
335
|
+
end.join("\n ")
|
297
336
|
end
|
298
337
|
|
299
338
|
def count_message(count, expectation_count_type=nil)
|
@@ -305,6 +344,19 @@ module RSpec
|
|
305
344
|
def times(count)
|
306
345
|
"#{count} time#{count == 1 ? '' : 's'}"
|
307
346
|
end
|
347
|
+
|
348
|
+
def grouped_args(args)
|
349
|
+
Hash[args.group_by { |x| x }.map { |k, v| [k, v.count] }]
|
350
|
+
end
|
351
|
+
|
352
|
+
def group_count(index, args)
|
353
|
+
" (#{times(index)})" if args.size > 1 || index > 1
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# @private
|
358
|
+
def self.error_generator
|
359
|
+
@error_generator ||= ErrorGenerator.new
|
308
360
|
end
|
309
361
|
end
|
310
362
|
end
|