mocha 1.8.0 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +7 -30
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +56 -31
- data/RELEASE.md +166 -0
- data/Rakefile +15 -7
- data/init.rb +1 -3
- data/lib/mocha/any_instance_method.rb +11 -53
- data/lib/mocha/api.rb +119 -56
- data/lib/mocha/block_matcher.rb +31 -0
- data/lib/mocha/cardinality.rb +52 -34
- data/lib/mocha/class_methods.rb +17 -15
- data/lib/mocha/configuration.rb +351 -67
- data/lib/mocha/deprecation.rb +2 -1
- data/lib/mocha/detection/test_unit.rb +1 -3
- data/lib/mocha/exception_raiser.rb +2 -1
- data/lib/mocha/expectation.rb +120 -81
- data/lib/mocha/expectation_error.rb +1 -3
- data/lib/mocha/expectation_list.rb +6 -6
- data/lib/mocha/inspect.rb +30 -26
- data/lib/mocha/instance_method.rb +19 -2
- data/lib/mocha/integration/mini_test.rb +7 -0
- data/lib/mocha/integration/test_unit.rb +7 -0
- data/lib/mocha/integration.rb +1 -3
- data/lib/mocha/invocation.rb +77 -0
- data/lib/mocha/macos_version.rb +5 -0
- data/lib/mocha/minitest.rb +6 -1
- data/lib/mocha/mock.rb +80 -39
- data/lib/mocha/mockery.rb +34 -80
- data/lib/mocha/names.rb +1 -1
- data/lib/mocha/object_methods.rb +13 -19
- data/lib/mocha/parameter_matchers/all_of.rb +1 -1
- data/lib/mocha/parameter_matchers/any_of.rb +1 -1
- data/lib/mocha/parameter_matchers/equivalent_uri.rb +0 -9
- data/lib/mocha/parameter_matchers/has_entries.rb +2 -3
- data/lib/mocha/parameter_matchers/has_entry.rb +24 -16
- data/lib/mocha/parameter_matchers/has_key.rb +2 -3
- data/lib/mocha/parameter_matchers/has_keys.rb +53 -0
- data/lib/mocha/parameter_matchers/has_value.rb +2 -3
- data/lib/mocha/parameter_matchers/includes.rb +2 -0
- data/lib/mocha/parameter_matchers/instance_methods.rb +18 -0
- data/lib/mocha/parameter_matchers/is_a.rb +2 -3
- data/lib/mocha/parameter_matchers/not.rb +2 -3
- data/lib/mocha/parameter_matchers.rb +2 -1
- data/lib/mocha/raised_exception.rb +11 -0
- data/lib/mocha/return_values.rb +3 -3
- data/lib/mocha/setup.rb +5 -0
- data/lib/mocha/single_return_value.rb +2 -1
- data/lib/mocha/singleton_class.rb +9 -0
- data/lib/mocha/state_machine.rb +31 -40
- data/lib/mocha/stubbed_method.rb +125 -0
- data/lib/mocha/test_unit.rb +6 -1
- data/lib/mocha/thrower.rb +2 -1
- data/lib/mocha/thrown_object.rb +12 -0
- data/lib/mocha/version.rb +1 -1
- data/lib/mocha/yield_parameters.rb +5 -11
- data/lib/mocha.rb +8 -0
- data/mocha.gemspec +14 -10
- metadata +16 -233
- data/bin/build-matrix +0 -83
- data/docs/CNAME +0 -1
- data/docs/Mocha/API.html +0 -1056
- data/docs/Mocha/ClassMethods.html +0 -267
- data/docs/Mocha/Configuration.html +0 -626
- data/docs/Mocha/Expectation.html +0 -2709
- data/docs/Mocha/ExpectationError.html +0 -157
- data/docs/Mocha/ExpectationErrorFactory.html +0 -269
- data/docs/Mocha/Hooks.html +0 -385
- data/docs/Mocha/Integration/MiniTest/Adapter.html +0 -165
- data/docs/Mocha/Integration/MiniTest.html +0 -123
- data/docs/Mocha/Integration/TestUnit/Adapter.html +0 -165
- data/docs/Mocha/Integration/TestUnit.html +0 -123
- data/docs/Mocha/Integration.html +0 -125
- data/docs/Mocha/Mock.html +0 -1197
- data/docs/Mocha/ObjectMethods.html +0 -712
- data/docs/Mocha/ParameterMatchers/AllOf.html +0 -154
- data/docs/Mocha/ParameterMatchers/AnyOf.html +0 -154
- data/docs/Mocha/ParameterMatchers/AnyParameters.html +0 -153
- data/docs/Mocha/ParameterMatchers/Anything.html +0 -153
- data/docs/Mocha/ParameterMatchers/Base.html +0 -448
- data/docs/Mocha/ParameterMatchers/Equals.html +0 -154
- data/docs/Mocha/ParameterMatchers/EquivalentUri.html +0 -153
- data/docs/Mocha/ParameterMatchers/HasEntries.html +0 -154
- data/docs/Mocha/ParameterMatchers/HasEntry.html +0 -154
- data/docs/Mocha/ParameterMatchers/HasKey.html +0 -154
- data/docs/Mocha/ParameterMatchers/HasValue.html +0 -154
- data/docs/Mocha/ParameterMatchers/Includes.html +0 -154
- data/docs/Mocha/ParameterMatchers/InstanceOf.html +0 -154
- data/docs/Mocha/ParameterMatchers/IsA.html +0 -153
- data/docs/Mocha/ParameterMatchers/KindOf.html +0 -154
- data/docs/Mocha/ParameterMatchers/Not.html +0 -154
- data/docs/Mocha/ParameterMatchers/Optionally.html +0 -153
- data/docs/Mocha/ParameterMatchers/RegexpMatches.html +0 -154
- data/docs/Mocha/ParameterMatchers/RespondsWith.html +0 -154
- data/docs/Mocha/ParameterMatchers/YamlEquivalent.html +0 -154
- data/docs/Mocha/ParameterMatchers.html +0 -3049
- data/docs/Mocha/Sequence.html +0 -149
- data/docs/Mocha/StateMachine/State.html +0 -141
- data/docs/Mocha/StateMachine/StatePredicate.html +0 -141
- data/docs/Mocha/StateMachine.html +0 -539
- data/docs/Mocha/StubbingError.html +0 -150
- data/docs/Mocha/UnexpectedInvocation.html +0 -140
- data/docs/Mocha.html +0 -127
- data/docs/_index.html +0 -537
- data/docs/class_list.html +0 -51
- data/docs/css/common.css +0 -1
- data/docs/css/full_list.css +0 -58
- data/docs/css/style.css +0 -496
- data/docs/file.COPYING.html +0 -81
- data/docs/file.MIT-LICENSE.html +0 -85
- data/docs/file.README.html +0 -418
- data/docs/file.RELEASE.html +0 -875
- data/docs/file_list.html +0 -71
- data/docs/frames.html +0 -17
- data/docs/index.html +0 -418
- data/docs/js/app.js +0 -292
- data/docs/js/full_list.js +0 -216
- data/docs/js/jquery.js +0 -4
- data/docs/method_list.html +0 -571
- data/docs/top-level-namespace.html +0 -118
- data/gemfiles/Gemfile.minitest.1.3.0 +0 -7
- data/gemfiles/Gemfile.minitest.1.4.0 +0 -7
- data/gemfiles/Gemfile.minitest.1.4.1 +0 -7
- data/gemfiles/Gemfile.minitest.1.4.2 +0 -7
- data/gemfiles/Gemfile.minitest.2.0.0 +0 -7
- data/gemfiles/Gemfile.minitest.2.0.1 +0 -7
- data/gemfiles/Gemfile.minitest.2.11.0 +0 -7
- data/gemfiles/Gemfile.minitest.2.11.2 +0 -7
- data/gemfiles/Gemfile.minitest.2.3.0 +0 -7
- data/gemfiles/Gemfile.test-unit.2.0.0 +0 -7
- data/gemfiles/Gemfile.test-unit.2.0.1 +0 -7
- data/gemfiles/Gemfile.test-unit.2.0.3 +0 -7
- data/lib/mocha/class_method.rb +0 -113
- data/lib/mocha/mini_test.rb +0 -5
- data/lib/mocha/module_method.rb +0 -6
- data/lib/mocha/module_methods.rb +0 -10
- data/lib/mocha/multiple_yields.rb +0 -15
- data/lib/mocha/no_yields.rb +0 -5
- data/lib/mocha/parameter_matchers/object.rb +0 -15
- data/lib/mocha/pretty_parameters.rb +0 -24
- data/lib/mocha/single_yield.rb +0 -13
- data/lib/mocha/standalone.rb +0 -4
- data/lib/mocha/unexpected_invocation.rb +0 -24
- data/lib/mocha_standalone.rb +0 -4
- data/test/acceptance/acceptance_test_helper.rb +0 -35
- data/test/acceptance/bug_18914_test.rb +0 -38
- data/test/acceptance/bug_21465_test.rb +0 -32
- data/test/acceptance/bug_21563_test.rb +0 -23
- data/test/acceptance/exception_rescue_test.rb +0 -54
- data/test/acceptance/expectations_on_multiple_methods_test.rb +0 -56
- data/test/acceptance/expected_invocation_count_test.rb +0 -230
- data/test/acceptance/failure_messages_test.rb +0 -62
- data/test/acceptance/issue_272_test.rb +0 -51
- data/test/acceptance/issue_65_test.rb +0 -65
- data/test/acceptance/issue_70_test.rb +0 -54
- data/test/acceptance/mocha_example_test.rb +0 -97
- data/test/acceptance/mocha_test_result_test.rb +0 -84
- data/test/acceptance/mock_test.rb +0 -98
- data/test/acceptance/mock_with_initializer_block_test.rb +0 -56
- data/test/acceptance/mocked_methods_dispatch_test.rb +0 -76
- data/test/acceptance/multiple_expectations_failure_message_test.rb +0 -67
- data/test/acceptance/optional_parameters_test.rb +0 -68
- data/test/acceptance/parameter_matcher_test.rb +0 -300
- data/test/acceptance/partial_mocks_test.rb +0 -45
- data/test/acceptance/prepend_test.rb +0 -87
- data/test/acceptance/prevent_use_of_mocha_outside_test_test.rb +0 -77
- data/test/acceptance/raise_exception_test.rb +0 -37
- data/test/acceptance/return_value_test.rb +0 -50
- data/test/acceptance/sequence_test.rb +0 -190
- data/test/acceptance/states_test.rb +0 -72
- data/test/acceptance/stub_any_instance_method_defined_on_superclass_test.rb +0 -65
- data/test/acceptance/stub_any_instance_method_test.rb +0 -282
- data/test/acceptance/stub_class_method_defined_on_active_record_association_proxy_test.rb +0 -106
- data/test/acceptance/stub_class_method_defined_on_class_test.rb +0 -79
- data/test/acceptance/stub_class_method_defined_on_module_test.rb +0 -74
- data/test/acceptance/stub_class_method_defined_on_superclass_test.rb +0 -145
- data/test/acceptance/stub_everything_test.rb +0 -54
- data/test/acceptance/stub_instance_method_defined_on_active_record_association_proxy_test.rb +0 -92
- data/test/acceptance/stub_instance_method_defined_on_class_and_aliased_test.rb +0 -68
- data/test/acceptance/stub_instance_method_defined_on_class_test.rb +0 -68
- data/test/acceptance/stub_instance_method_defined_on_kernel_module_test.rb +0 -137
- data/test/acceptance/stub_instance_method_defined_on_module_test.rb +0 -77
- data/test/acceptance/stub_instance_method_defined_on_object_class_test.rb +0 -76
- data/test/acceptance/stub_instance_method_defined_on_singleton_class_test.rb +0 -68
- data/test/acceptance/stub_instance_method_defined_on_superclass_test.rb +0 -71
- data/test/acceptance/stub_method_defined_on_module_and_aliased_test.rb +0 -39
- data/test/acceptance/stub_module_method_test.rb +0 -201
- data/test/acceptance/stub_test.rb +0 -50
- data/test/acceptance/stubba_example_test.rb +0 -94
- data/test/acceptance/stubba_test_result_test.rb +0 -72
- data/test/acceptance/stubbing_error_backtrace_test.rb +0 -64
- data/test/acceptance/stubbing_frozen_object_test.rb +0 -89
- data/test/acceptance/stubbing_method_accepting_block_parameter_test.rb +0 -53
- data/test/acceptance/stubbing_method_unnecessarily_test.rb +0 -63
- data/test/acceptance/stubbing_nil_test.rb +0 -60
- data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +0 -141
- data/test/acceptance/stubbing_non_existent_class_method_test.rb +0 -157
- data/test/acceptance/stubbing_non_existent_instance_method_test.rb +0 -145
- data/test/acceptance/stubbing_non_public_any_instance_method_test.rb +0 -128
- data/test/acceptance/stubbing_non_public_class_method_test.rb +0 -163
- data/test/acceptance/stubbing_non_public_instance_method_test.rb +0 -141
- data/test/acceptance/stubbing_on_non_mock_object_test.rb +0 -70
- data/test/acceptance/stubbing_same_class_method_on_parent_and_child_classes_test.rb +0 -34
- data/test/acceptance/throw_test.rb +0 -43
- data/test/acceptance/unexpected_invocation_test.rb +0 -24
- data/test/acceptance/unstubbing_test.rb +0 -195
- data/test/assertions.rb +0 -8
- data/test/deprecation_disabler.rb +0 -15
- data/test/execution_point.rb +0 -36
- data/test/integration/mini_test_test.rb +0 -8
- data/test/integration/shared_tests.rb +0 -176
- data/test/integration/test_unit_test.rb +0 -8
- data/test/method_definer.rb +0 -22
- data/test/mini_test_result.rb +0 -96
- data/test/minitest_result.rb +0 -48
- data/test/simple_counter.rb +0 -11
- data/test/test_helper.rb +0 -58
- data/test/test_runner.rb +0 -56
- data/test/test_unit_result.rb +0 -22
- data/test/unit/any_instance_method_test.rb +0 -150
- data/test/unit/array_inspect_test.rb +0 -14
- data/test/unit/backtrace_filter_test.rb +0 -17
- data/test/unit/cardinality_test.rb +0 -54
- data/test/unit/central_test.rb +0 -99
- data/test/unit/change_state_side_effect_test.rb +0 -37
- data/test/unit/class_method_test.rb +0 -254
- data/test/unit/class_methods_test.rb +0 -69
- data/test/unit/configuration_test.rb +0 -37
- data/test/unit/date_time_inspect_test.rb +0 -19
- data/test/unit/exception_raiser_test.rb +0 -40
- data/test/unit/expectation_list_test.rb +0 -80
- data/test/unit/expectation_test.rb +0 -492
- data/test/unit/hash_inspect_test.rb +0 -14
- data/test/unit/hooks_test.rb +0 -35
- data/test/unit/in_state_ordering_constraint_test.rb +0 -39
- data/test/unit/method_matcher_test.rb +0 -26
- data/test/unit/mock_test.rb +0 -363
- data/test/unit/mockery_test.rb +0 -174
- data/test/unit/module_methods_test.rb +0 -17
- data/test/unit/multiple_yields_test.rb +0 -16
- data/test/unit/no_yields_test.rb +0 -16
- data/test/unit/object_inspect_test.rb +0 -58
- data/test/unit/object_methods_test.rb +0 -62
- data/test/unit/parameter_matchers/all_of_test.rb +0 -24
- data/test/unit/parameter_matchers/any_of_test.rb +0 -24
- data/test/unit/parameter_matchers/anything_test.rb +0 -19
- data/test/unit/parameter_matchers/equals_test.rb +0 -23
- data/test/unit/parameter_matchers/equivalent_uri_test.rb +0 -50
- data/test/unit/parameter_matchers/has_entries_test.rb +0 -51
- data/test/unit/parameter_matchers/has_entry_test.rb +0 -128
- data/test/unit/parameter_matchers/has_key_test.rb +0 -54
- data/test/unit/parameter_matchers/has_value_test.rb +0 -55
- data/test/unit/parameter_matchers/includes_test.rb +0 -106
- data/test/unit/parameter_matchers/instance_of_test.rb +0 -23
- data/test/unit/parameter_matchers/is_a_test.rb +0 -23
- data/test/unit/parameter_matchers/kind_of_test.rb +0 -23
- data/test/unit/parameter_matchers/not_test.rb +0 -24
- data/test/unit/parameter_matchers/regexp_matches_test.rb +0 -45
- data/test/unit/parameter_matchers/responds_with_test.rb +0 -38
- data/test/unit/parameter_matchers/stub_matcher.rb +0 -23
- data/test/unit/parameter_matchers/yaml_equivalent_test.rb +0 -23
- data/test/unit/parameters_matcher_test.rb +0 -119
- data/test/unit/receivers_test.rb +0 -96
- data/test/unit/return_values_test.rb +0 -61
- data/test/unit/sequence_test.rb +0 -100
- data/test/unit/single_return_value_test.rb +0 -12
- data/test/unit/single_yield_test.rb +0 -16
- data/test/unit/state_machine_test.rb +0 -96
- data/test/unit/string_inspect_test.rb +0 -9
- data/test/unit/thrower_test.rb +0 -18
- data/test/unit/yield_parameters_test.rb +0 -91
data/lib/mocha/minitest.rb
CHANGED
data/lib/mocha/mock.rb
CHANGED
@@ -1,21 +1,27 @@
|
|
1
|
-
require '
|
1
|
+
require 'mocha/singleton_class'
|
2
2
|
require 'mocha/expectation'
|
3
3
|
require 'mocha/expectation_list'
|
4
|
+
require 'mocha/invocation'
|
4
5
|
require 'mocha/names'
|
5
6
|
require 'mocha/receivers'
|
6
7
|
require 'mocha/method_matcher'
|
7
8
|
require 'mocha/parameters_matcher'
|
8
|
-
require 'mocha/unexpected_invocation'
|
9
9
|
require 'mocha/argument_iterator'
|
10
10
|
require 'mocha/expectation_error_factory'
|
11
|
-
require 'mocha/deprecation'
|
12
11
|
require 'mocha/ruby_version'
|
13
12
|
|
14
13
|
module Mocha
|
15
14
|
# Traditional mock object.
|
16
15
|
#
|
17
|
-
#
|
18
|
-
# methods on {Expectation}.
|
16
|
+
# {expects} and {stubs} return an {Expectation} which can be further modified
|
17
|
+
# by methods on {Expectation}.
|
18
|
+
#
|
19
|
+
# {responds_like} and {responds_like_instance_of} both return a {Mock}, and
|
20
|
+
# can therefore, be chained to the original creation methods in {API}.
|
21
|
+
# They force the mock to indicate what it is supposed to be mocking, thus
|
22
|
+
# making it a safer verifying mock. They check that the underlying +responder+
|
23
|
+
# will actually respond to the methods being stubbed, throwing a
|
24
|
+
# +NoMethodError+ upon invocation otherwise.
|
19
25
|
#
|
20
26
|
# Stubs and expectations are basically the same thing. A stub is just an
|
21
27
|
# expectation of zero or more invocations. The {#stubs} method is syntactic
|
@@ -70,12 +76,12 @@ module Mocha
|
|
70
76
|
class Mock
|
71
77
|
# Adds an expectation that the specified method must be called exactly once with any parameters.
|
72
78
|
#
|
73
|
-
# @
|
74
|
-
# @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {#expects} were called multiple times.
|
79
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
75
80
|
#
|
76
81
|
# @overload def expects(method_name)
|
82
|
+
# @param [Symbol,String] method_name name of expected method
|
77
83
|
# @overload def expects(expected_methods_vs_return_values)
|
78
|
-
#
|
84
|
+
# @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {#expects} were called multiple times.
|
79
85
|
#
|
80
86
|
# @example Expected method invoked once so no error raised
|
81
87
|
# object = mock()
|
@@ -115,12 +121,12 @@ module Mocha
|
|
115
121
|
|
116
122
|
# Adds an expectation that the specified method may be called any number of times with any parameters.
|
117
123
|
#
|
118
|
-
# @
|
119
|
-
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {#stubs} were called multiple times.
|
124
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
120
125
|
#
|
121
126
|
# @overload def stubs(method_name)
|
127
|
+
# @param [Symbol,String] method_name name of stubbed method
|
122
128
|
# @overload def stubs(stubbed_methods_vs_return_values)
|
123
|
-
#
|
129
|
+
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {#stubs} were called multiple times.
|
124
130
|
#
|
125
131
|
# @example No error raised however many times stubbed method is invoked
|
126
132
|
# object = mock()
|
@@ -150,9 +156,9 @@ module Mocha
|
|
150
156
|
end
|
151
157
|
end
|
152
158
|
|
153
|
-
# Removes the specified stubbed
|
159
|
+
# Removes the specified stubbed methods (added by calls to {#expects} or {#stubs}) and all expectations associated with them.
|
154
160
|
#
|
155
|
-
# @param [Symbol]
|
161
|
+
# @param [Array<Symbol>] method_names names of methods to unstub.
|
156
162
|
#
|
157
163
|
# @example Invoking an unstubbed method causes error to be raised
|
158
164
|
# object = mock('mock') do
|
@@ -160,8 +166,18 @@ module Mocha
|
|
160
166
|
# object.stubbed_method # => :result_one
|
161
167
|
# object.unstub(:stubbed_method)
|
162
168
|
# object.stubbed_method # => unexpected invocation: #<Mock:mock>.stubbed_method()
|
163
|
-
|
164
|
-
|
169
|
+
#
|
170
|
+
# @example Unstubbing multiple methods.
|
171
|
+
# multiplier.unstub(:double, :triple)
|
172
|
+
#
|
173
|
+
# # exactly equivalent to
|
174
|
+
#
|
175
|
+
# multiplier.unstub(:double)
|
176
|
+
# multiplier.unstub(:triple)
|
177
|
+
def unstub(*method_names)
|
178
|
+
method_names.each do |method_name|
|
179
|
+
@expectations.remove_all_matching_method(method_name)
|
180
|
+
end
|
165
181
|
end
|
166
182
|
|
167
183
|
# Constrains the {Mock} instance so that it can only expect or stub methods to which +responder+ responds. The constraint is only applied at method invocation time.
|
@@ -251,7 +267,7 @@ module Mocha
|
|
251
267
|
end
|
252
268
|
|
253
269
|
# @private
|
254
|
-
def initialize(mockery, name = nil, receiver = nil
|
270
|
+
def initialize(mockery, name = nil, receiver = nil)
|
255
271
|
@mockery = mockery
|
256
272
|
@name = name || DefaultName.new(self)
|
257
273
|
@receiver = receiver || DefaultReceiver.new(self)
|
@@ -259,9 +275,7 @@ module Mocha
|
|
259
275
|
@everything_stubbed = false
|
260
276
|
@responder = nil
|
261
277
|
@unexpected_invocation = nil
|
262
|
-
|
263
|
-
Deprecation.warning('Passing a block is deprecated. Use Object#tap or define stubs/expectations with an explicit receiver instead.')
|
264
|
-
instance_eval(&block)
|
278
|
+
@expired = false
|
265
279
|
end
|
266
280
|
|
267
281
|
# @private
|
@@ -271,6 +285,8 @@ module Mocha
|
|
271
285
|
|
272
286
|
alias_method :__stubs__, :stubs
|
273
287
|
|
288
|
+
alias_method :__singleton_class__, :singleton_class
|
289
|
+
|
274
290
|
alias_method :quacks_like, :responds_like
|
275
291
|
alias_method :quacks_like_instance_of, :responds_like_instance_of
|
276
292
|
|
@@ -290,26 +306,16 @@ module Mocha
|
|
290
306
|
end
|
291
307
|
|
292
308
|
# @private
|
293
|
-
# rubocop:disable Style/MethodMissingSuper
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
if @unexpected_invocation.nil?
|
302
|
-
@unexpected_invocation = UnexpectedInvocation.new(self, symbol, *arguments)
|
303
|
-
matching_expectation.invoke(&block) if matching_expectation
|
304
|
-
message = @unexpected_invocation.full_description
|
305
|
-
message << @mockery.mocha_inspect
|
306
|
-
else
|
307
|
-
message = @unexpected_invocation.short_description
|
308
|
-
end
|
309
|
-
raise ExpectationErrorFactory.build(message, caller)
|
309
|
+
def method_missing(symbol, *arguments, &block) # rubocop:disable Style/MethodMissingSuper
|
310
|
+
check_expiry
|
311
|
+
check_responder_responds_to(symbol)
|
312
|
+
invocation = Invocation.new(self, symbol, *arguments, &block)
|
313
|
+
if (matching_expectation_allowing_invocation = all_expectations.match_allowing_invocation(invocation))
|
314
|
+
matching_expectation_allowing_invocation.invoke(invocation)
|
315
|
+
elsif (matching_expectation = all_expectations.match(invocation)) || (!matching_expectation && !@everything_stubbed)
|
316
|
+
raise_unexpected_invocation_error(invocation, matching_expectation)
|
310
317
|
end
|
311
318
|
end
|
312
|
-
# rubocop:enable Style/MethodMissingSuper
|
313
319
|
|
314
320
|
# @private
|
315
321
|
def respond_to_missing?(symbol, include_private = false)
|
@@ -324,8 +330,8 @@ module Mocha
|
|
324
330
|
end
|
325
331
|
end
|
326
332
|
|
327
|
-
# @private
|
328
333
|
if PRE_RUBY_V19
|
334
|
+
# @private
|
329
335
|
def respond_to?(symbol, include_private = false)
|
330
336
|
respond_to_missing?(symbol, include_private)
|
331
337
|
end
|
@@ -336,6 +342,11 @@ module Mocha
|
|
336
342
|
@expectations.verified?(assertion_counter)
|
337
343
|
end
|
338
344
|
|
345
|
+
# @private
|
346
|
+
def __expire__
|
347
|
+
@expired = true
|
348
|
+
end
|
349
|
+
|
339
350
|
# @private
|
340
351
|
def mocha_inspect
|
341
352
|
@name.mocha_inspect
|
@@ -348,12 +359,42 @@ module Mocha
|
|
348
359
|
|
349
360
|
# @private
|
350
361
|
def ensure_method_not_already_defined(method_name)
|
351
|
-
|
362
|
+
__singleton_class__.send(:undef_method, method_name) if __singleton_class__.method_defined?(method_name) || __singleton_class__.private_method_defined?(method_name)
|
352
363
|
end
|
353
364
|
|
354
365
|
# @private
|
355
366
|
def any_expectations?
|
356
367
|
@expectations.any?
|
357
368
|
end
|
369
|
+
|
370
|
+
private
|
371
|
+
|
372
|
+
def raise_unexpected_invocation_error(invocation, matching_expectation)
|
373
|
+
if @unexpected_invocation.nil?
|
374
|
+
@unexpected_invocation = invocation
|
375
|
+
matching_expectation.invoke(invocation) if matching_expectation
|
376
|
+
message = "#{@unexpected_invocation.call_description}\n#{@mockery.mocha_inspect}"
|
377
|
+
else
|
378
|
+
message = @unexpected_invocation.short_call_description
|
379
|
+
end
|
380
|
+
raise ExpectationErrorFactory.build("unexpected invocation: #{message}", caller)
|
381
|
+
end
|
382
|
+
|
383
|
+
def check_responder_responds_to(symbol)
|
384
|
+
if @responder && !@responder.respond_to?(symbol) # rubocop:disable Style/GuardClause
|
385
|
+
raise NoMethodError, "undefined method `#{symbol}' for #{mocha_inspect} which responds like #{@responder.mocha_inspect}"
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
def check_expiry
|
390
|
+
if @expired # rubocop:disable Style/GuardClause
|
391
|
+
Deprecation.warning(
|
392
|
+
"#{mocha_inspect} was instantiated in one test but it is receiving invocations within another test.",
|
393
|
+
' This can lead to unintended interactions between tests and hence unexpected test failures.',
|
394
|
+
' Ensure that every test correctly cleans up any state that it introduces.',
|
395
|
+
' A Mocha::StubbingError will be raised in this scenario in the future.'
|
396
|
+
)
|
397
|
+
end
|
398
|
+
end
|
358
399
|
end
|
359
400
|
end
|
data/lib/mocha/mockery.rb
CHANGED
@@ -35,12 +35,13 @@ module Mocha
|
|
35
35
|
|
36
36
|
class << self
|
37
37
|
def instance
|
38
|
-
instances.last || Null.new
|
38
|
+
@instances.last || Null.new
|
39
39
|
end
|
40
40
|
|
41
41
|
def setup
|
42
|
+
@instances ||= []
|
42
43
|
mockery = new
|
43
|
-
mockery.logger = instance.logger unless instances.empty?
|
44
|
+
mockery.logger = instance.logger unless @instances.empty?
|
44
45
|
@instances.push(mockery)
|
45
46
|
end
|
46
47
|
|
@@ -52,30 +53,23 @@ module Mocha
|
|
52
53
|
instance.teardown
|
53
54
|
ensure
|
54
55
|
@instances.pop
|
55
|
-
@instances = nil if instances.empty?
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def instances
|
61
|
-
@instances ||= []
|
62
56
|
end
|
63
57
|
end
|
64
58
|
|
65
|
-
def named_mock(name
|
66
|
-
add_mock(Mock.new(self, Name.new(name)
|
59
|
+
def named_mock(name)
|
60
|
+
add_mock(Mock.new(self, Name.new(name)))
|
67
61
|
end
|
68
62
|
|
69
|
-
def unnamed_mock
|
70
|
-
add_mock(Mock.new(self
|
63
|
+
def unnamed_mock
|
64
|
+
add_mock(Mock.new(self))
|
71
65
|
end
|
72
66
|
|
73
|
-
def mock_impersonating(object
|
74
|
-
add_mock(Mock.new(self, ImpersonatingName.new(object), ObjectReceiver.new(object)
|
67
|
+
def mock_impersonating(object)
|
68
|
+
add_mock(Mock.new(self, ImpersonatingName.new(object), ObjectReceiver.new(object)))
|
75
69
|
end
|
76
70
|
|
77
|
-
def mock_impersonating_any_instance_of(klass
|
78
|
-
add_mock(Mock.new(self, ImpersonatingAnyInstanceName.new(klass), AnyInstanceReceiver.new(klass)
|
71
|
+
def mock_impersonating_any_instance_of(klass)
|
72
|
+
add_mock(Mock.new(self, ImpersonatingAnyInstanceName.new(klass), AnyInstanceReceiver.new(klass)))
|
79
73
|
end
|
80
74
|
|
81
75
|
def new_state_machine(name)
|
@@ -92,16 +86,15 @@ module Mocha
|
|
92
86
|
end
|
93
87
|
raise ExpectationErrorFactory.build(message, backtrace)
|
94
88
|
end
|
95
|
-
expectations.each do |
|
96
|
-
|
97
|
-
|
98
|
-
on_stubbing_method_unnecessarily(e)
|
99
|
-
end
|
89
|
+
expectations.reject(&:used?).each do |expectation|
|
90
|
+
signature_proc = lambda { expectation.method_signature }
|
91
|
+
check(:stubbing_method_unnecessarily, 'method unnecessarily', signature_proc, expectation.backtrace)
|
100
92
|
end
|
101
93
|
end
|
102
94
|
|
103
95
|
def teardown
|
104
96
|
stubba.unstub_all
|
97
|
+
mocks.each(&:__expire__)
|
105
98
|
reset
|
106
99
|
end
|
107
100
|
|
@@ -119,71 +112,23 @@ module Mocha
|
|
119
112
|
|
120
113
|
def mocha_inspect
|
121
114
|
message = ''
|
122
|
-
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n"
|
123
|
-
message << "satisfied expectations:\n- #{satisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n"
|
124
|
-
message << "states:\n- #{state_machines.map(&:mocha_inspect).join("\n- ")}"
|
115
|
+
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n" if unsatisfied_expectations.any?
|
116
|
+
message << "satisfied expectations:\n- #{satisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n" if satisfied_expectations.any?
|
117
|
+
message << "states:\n- #{state_machines.map(&:mocha_inspect).join("\n- ")}\n" if state_machines.any?
|
125
118
|
message
|
126
119
|
end
|
127
120
|
|
128
121
|
def on_stubbing(object, method)
|
129
122
|
method = PRE_RUBY_V19 ? method.to_s : method.to_sym
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
134
|
-
end
|
135
|
-
unless Mocha::Configuration.allow?(:stubbing_non_public_method)
|
136
|
-
if object.method_exists?(method, false)
|
137
|
-
on_stubbing_non_public_method(object, method)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
unless Mocha::Configuration.allow?(:stubbing_method_on_nil)
|
141
|
-
if object.nil?
|
142
|
-
on_stubbing_method_on_nil(object, method)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
return if Mocha::Configuration.allow?(:stubbing_method_on_non_mock_object)
|
146
|
-
on_stubbing_method_on_non_mock_object(object, method)
|
147
|
-
end
|
148
|
-
|
149
|
-
def on_stubbing_non_existent_method(object, method)
|
150
|
-
if Mocha::Configuration.prevent?(:stubbing_non_existent_method)
|
151
|
-
raise StubbingError.new("stubbing non-existent method: #{object.mocha_inspect}.#{method}", caller)
|
152
|
-
end
|
153
|
-
return unless Mocha::Configuration.warn_when?(:stubbing_non_existent_method)
|
154
|
-
logger.warn "stubbing non-existent method: #{object.mocha_inspect}.#{method}"
|
155
|
-
end
|
156
|
-
|
157
|
-
def on_stubbing_non_public_method(object, method)
|
158
|
-
if Mocha::Configuration.prevent?(:stubbing_non_public_method)
|
159
|
-
raise StubbingError.new("stubbing non-public method: #{object.mocha_inspect}.#{method}", caller)
|
160
|
-
end
|
161
|
-
return unless Mocha::Configuration.warn_when?(:stubbing_non_public_method)
|
162
|
-
logger.warn "stubbing non-public method: #{object.mocha_inspect}.#{method}"
|
163
|
-
end
|
164
|
-
|
165
|
-
def on_stubbing_method_on_nil(object, method)
|
166
|
-
if Mocha::Configuration.prevent?(:stubbing_method_on_nil)
|
167
|
-
raise StubbingError.new("stubbing method on nil: #{object.mocha_inspect}.#{method}", caller)
|
168
|
-
end
|
169
|
-
return unless Mocha::Configuration.warn_when?(:stubbing_method_on_nil)
|
170
|
-
logger.warn "stubbing method on nil: #{object.mocha_inspect}.#{method}"
|
171
|
-
end
|
172
|
-
|
173
|
-
def on_stubbing_method_on_non_mock_object(object, method)
|
174
|
-
if Mocha::Configuration.prevent?(:stubbing_method_on_non_mock_object)
|
175
|
-
raise StubbingError.new("stubbing method on non-mock object: #{object.mocha_inspect}.#{method}", caller)
|
123
|
+
signature_proc = lambda { "#{object.mocha_inspect}.#{method}" }
|
124
|
+
check(:stubbing_non_existent_method, 'non-existent method', signature_proc) do
|
125
|
+
!(object.stubba_class.__method_exists__?(method, true) || object.respond_to?(method.to_sym))
|
176
126
|
end
|
177
|
-
|
178
|
-
|
179
|
-
end
|
180
|
-
|
181
|
-
def on_stubbing_method_unnecessarily(expectation)
|
182
|
-
if Mocha::Configuration.prevent?(:stubbing_method_unnecessarily)
|
183
|
-
raise StubbingError.new("stubbing method unnecessarily: #{expectation.method_signature}", expectation.backtrace)
|
127
|
+
check(:stubbing_non_public_method, 'non-public method', signature_proc) do
|
128
|
+
object.stubba_class.__method_exists__?(method, false)
|
184
129
|
end
|
185
|
-
|
186
|
-
|
130
|
+
check(:stubbing_method_on_nil, 'method on nil', signature_proc) { object.nil? }
|
131
|
+
check(:stubbing_method_on_non_mock_object, 'method on non-mock object', signature_proc)
|
187
132
|
end
|
188
133
|
|
189
134
|
attr_writer :logger
|
@@ -194,6 +139,15 @@ module Mocha
|
|
194
139
|
|
195
140
|
private
|
196
141
|
|
142
|
+
def check(action, description, signature_proc, backtrace = caller)
|
143
|
+
treatment = Mocha.configuration.send(action)
|
144
|
+
return if (treatment == :allow) || (block_given? && !yield)
|
145
|
+
method_signature = signature_proc.call
|
146
|
+
message = "stubbing #{description}: #{method_signature}"
|
147
|
+
raise StubbingError.new(message, backtrace) if treatment == :prevent
|
148
|
+
logger.warn(message) if treatment == :warn
|
149
|
+
end
|
150
|
+
|
197
151
|
def expectations
|
198
152
|
mocks.map { |mock| mock.__expectations__.to_a }.flatten
|
199
153
|
end
|
data/lib/mocha/names.rb
CHANGED
data/lib/mocha/object_methods.rb
CHANGED
@@ -35,17 +35,22 @@ module Mocha
|
|
35
35
|
self
|
36
36
|
end
|
37
37
|
|
38
|
+
# @private
|
39
|
+
def stubba_class
|
40
|
+
singleton_class
|
41
|
+
end
|
42
|
+
|
38
43
|
# Adds an expectation that the specified method must be called exactly once with any parameters.
|
39
44
|
#
|
40
45
|
# The original implementation of the method is replaced during the test and then restored at the end of the test. The temporary replacement method has the same visibility as the original method.
|
41
46
|
#
|
42
|
-
# @
|
43
|
-
# @
|
47
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
48
|
+
# @raise [StubbingError] if attempting to stub method which is not allowed.
|
44
49
|
#
|
45
50
|
# @overload def expects(method_name)
|
51
|
+
# @param [Symbol,String] method_name name of expected method
|
46
52
|
# @overload def expects(expected_methods_vs_return_values)
|
47
|
-
#
|
48
|
-
# @raise [StubbingError] if attempting to stub method which is not allowed.
|
53
|
+
# @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {#expects} were called multiple times.
|
49
54
|
#
|
50
55
|
# @example Setting up an expectation on a non-mock object.
|
51
56
|
# product = Product.new
|
@@ -88,13 +93,13 @@ module Mocha
|
|
88
93
|
#
|
89
94
|
# The original implementation of the method is replaced during the test and then restored at the end of the test. The temporary replacement method has the same visibility as the original method.
|
90
95
|
#
|
91
|
-
# @
|
92
|
-
# @
|
96
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
97
|
+
# @raise [StubbingError] if attempting to stub method which is not allowed.
|
93
98
|
#
|
94
99
|
# @overload def stubs(method_name)
|
100
|
+
# @param [Symbol,String] method_name name of stubbed method
|
95
101
|
# @overload def stubs(stubbed_methods_vs_return_values)
|
96
|
-
#
|
97
|
-
# @raise [StubbingError] if attempting to stub method which is not allowed.
|
102
|
+
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {#stubs} were called multiple times.
|
98
103
|
#
|
99
104
|
# @example Setting up a stubbed methods on a non-mock object.
|
100
105
|
# product = Product.new
|
@@ -160,16 +165,5 @@ module Mocha
|
|
160
165
|
mockery.stubba.unstub(method)
|
161
166
|
end
|
162
167
|
end
|
163
|
-
|
164
|
-
# @private
|
165
|
-
def method_exists?(method, include_public_methods = true)
|
166
|
-
if include_public_methods
|
167
|
-
return true if public_methods(true).include?(method)
|
168
|
-
return true if respond_to?(method.to_sym)
|
169
|
-
end
|
170
|
-
return true if protected_methods(true).include?(method)
|
171
|
-
return true if private_methods(true).include?(method)
|
172
|
-
false
|
173
|
-
end
|
174
168
|
end
|
175
169
|
end
|
@@ -4,7 +4,7 @@ module Mocha
|
|
4
4
|
module ParameterMatchers
|
5
5
|
# Matches if all +matchers+ match.
|
6
6
|
#
|
7
|
-
# @param [*Array<Base>]
|
7
|
+
# @param [*Array<Base>] matchers parameter matchers.
|
8
8
|
# @return [AllOf] parameter matcher.
|
9
9
|
#
|
10
10
|
# @see Expectation#with
|
@@ -4,7 +4,7 @@ module Mocha
|
|
4
4
|
module ParameterMatchers
|
5
5
|
# Matches if any +matchers+ match.
|
6
6
|
#
|
7
|
-
# @param [*Array<Base>]
|
7
|
+
# @param [*Array<Base>] matchers parameter matchers.
|
8
8
|
# @return [AnyOf] parameter matcher.
|
9
9
|
#
|
10
10
|
# @see Expectation#with
|
@@ -27,15 +27,6 @@ module Mocha
|
|
27
27
|
EquivalentUri.new(uri)
|
28
28
|
end
|
29
29
|
|
30
|
-
# @deprecated Use {#equivalent_uri} instead.
|
31
|
-
# rubocop:disable Naming/PredicateName
|
32
|
-
def has_equivalent_query_string(uri)
|
33
|
-
Mocha::Deprecation.warning('`has_equivalent_query_string` is deprecated. Please use `equivalent_uri` instead.')
|
34
|
-
|
35
|
-
equivalent_uri(uri)
|
36
|
-
end
|
37
|
-
# rubocop:enable Naming/PredicateName
|
38
|
-
|
39
30
|
# Parameter matcher which matches URIs with equivalent query strings.
|
40
31
|
class EquivalentUri < Base
|
41
32
|
# @private
|
@@ -22,11 +22,10 @@ module Mocha
|
|
22
22
|
# object.expects(:method_1).with(has_entries('key_1' => 1, 'key_2' => 2))
|
23
23
|
# object.method_1('key_1' => 1, 'key_2' => 99)
|
24
24
|
# # error raised, because method_1 was not called with Hash containing entries: 'key_1' => 1, 'key_2' => 2
|
25
|
-
#
|
26
|
-
def has_entries(entries)
|
25
|
+
#
|
26
|
+
def has_entries(entries) # rubocop:disable Naming/PredicateName
|
27
27
|
HasEntries.new(entries)
|
28
28
|
end
|
29
|
-
# rubocop:enable Naming/PredicateName
|
30
29
|
|
31
30
|
# Parameter matcher which matches when actual parameter contains all expected +Hash+ entries.
|
32
31
|
class HasEntries < Base
|
@@ -39,23 +39,13 @@ module Mocha
|
|
39
39
|
# object.expects(:method_1).with(has_entry('key_1' => 1))
|
40
40
|
# object.method_1('key_1' => 2, 'key_2' => 1)
|
41
41
|
# # error raised, because method_1 was not called with Hash containing entry: 'key_1' => 1
|
42
|
-
#
|
43
|
-
def has_entry(*options)
|
42
|
+
#
|
43
|
+
def has_entry(*options) # rubocop:disable Naming/PredicateName
|
44
44
|
case options.length
|
45
|
+
when 0
|
46
|
+
raise ArgumentError, 'No arguments. Expecting at least one.'
|
45
47
|
when 1
|
46
|
-
|
47
|
-
when Hash
|
48
|
-
case options[0].length
|
49
|
-
when 0
|
50
|
-
raise ArgumentError, 'Argument has no entries.'
|
51
|
-
when 1
|
52
|
-
key, value = options[0].first
|
53
|
-
else
|
54
|
-
raise ArgumentError, 'Argument has multiple entries. Use Mocha::ParameterMatchers#has_entries instead.'
|
55
|
-
end
|
56
|
-
else
|
57
|
-
raise ArgumentError, 'Argument is not a Hash.'
|
58
|
-
end
|
48
|
+
key, value = parse_option(options[0])
|
59
49
|
when 2
|
60
50
|
key, value = options
|
61
51
|
else
|
@@ -63,7 +53,6 @@ module Mocha
|
|
63
53
|
end
|
64
54
|
HasEntry.new(key, value)
|
65
55
|
end
|
66
|
-
# rubocop:enable Naming/PredicateName
|
67
56
|
|
68
57
|
# Parameter matcher which matches when actual parameter contains expected +Hash+ entry.
|
69
58
|
class HasEntry < Base
|
@@ -86,5 +75,24 @@ module Mocha
|
|
86
75
|
"has_entry(#{@key.mocha_inspect} => #{@value.mocha_inspect})"
|
87
76
|
end
|
88
77
|
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# @private
|
82
|
+
def parse_option(option)
|
83
|
+
case option
|
84
|
+
when Hash
|
85
|
+
case option.length
|
86
|
+
when 0
|
87
|
+
raise ArgumentError, 'Argument has no entries.'
|
88
|
+
when 1
|
89
|
+
option.first
|
90
|
+
else
|
91
|
+
raise ArgumentError, 'Argument has multiple entries. Use Mocha::ParameterMatchers#has_entries instead.'
|
92
|
+
end
|
93
|
+
else
|
94
|
+
raise ArgumentError, 'Argument is not a Hash.'
|
95
|
+
end
|
96
|
+
end
|
89
97
|
end
|
90
98
|
end
|
@@ -20,11 +20,10 @@ module Mocha
|
|
20
20
|
# object.expects(:method_1).with(has_key('key_1'))
|
21
21
|
# object.method_1('key_2' => 2)
|
22
22
|
# # error raised, because method_1 was not called with Hash containing key: 'key_1'
|
23
|
-
#
|
24
|
-
def has_key(key)
|
23
|
+
#
|
24
|
+
def has_key(key) # rubocop:disable Naming/PredicateName
|
25
25
|
HasKey.new(key)
|
26
26
|
end
|
27
|
-
# rubocop:enable Naming/PredicateName
|
28
27
|
|
29
28
|
# Parameter matcher which matches when actual parameter contains +Hash+ entry with expected key.
|
30
29
|
class HasKey < Base
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'mocha/parameter_matchers/base'
|
2
|
+
|
3
|
+
module Mocha
|
4
|
+
module ParameterMatchers
|
5
|
+
# Matches +Hash+ containing +keys+.
|
6
|
+
#
|
7
|
+
# @param [*Array<Object>] keys expected keys.
|
8
|
+
# @return [HasKeys] parameter matcher.
|
9
|
+
#
|
10
|
+
# @see Expectation#with
|
11
|
+
#
|
12
|
+
# @example Actual parameter contains entry with expected keys.
|
13
|
+
# object = mock()
|
14
|
+
# object.expects(:method_1).with(has_keys(:key_1, :key_2))
|
15
|
+
# object.method_1(:key_1 => 1, :key_2 => 2, :key_3 => 3)
|
16
|
+
# # no error raised
|
17
|
+
#
|
18
|
+
# @example Actual parameter does not contain all expected keys.
|
19
|
+
# object = mock()
|
20
|
+
# object.expects(:method_1).with(has_keys(:key_1, :key_2))
|
21
|
+
# object.method_1(:key_2 => 2)
|
22
|
+
# # error raised, because method_1 was not called with Hash containing key: :key_1
|
23
|
+
#
|
24
|
+
def has_keys(*keys) # rubocop:disable Naming/PredicateName
|
25
|
+
HasKeys.new(*keys)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Parameter matcher which matches when actual parameter contains +Hash+ with all expected keys.
|
29
|
+
class HasKeys < Base
|
30
|
+
# @private
|
31
|
+
def initialize(*keys)
|
32
|
+
raise ArgumentError, 'No arguments. Expecting at least one.' if keys.empty?
|
33
|
+
|
34
|
+
@keys = keys
|
35
|
+
end
|
36
|
+
|
37
|
+
# @private
|
38
|
+
def matches?(available_parameters)
|
39
|
+
parameter = available_parameters.shift
|
40
|
+
return false unless parameter.respond_to?(:keys)
|
41
|
+
|
42
|
+
@keys.map(&:to_matcher).all? do |matcher|
|
43
|
+
parameter.keys.any? { |key| matcher.matches?([key]) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @private
|
48
|
+
def mocha_inspect
|
49
|
+
"has_keys(#{@keys.mocha_inspect(false)})"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|