mocha 1.2.1 → 2.0.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 +5 -5
- data/.github/FUNDING.yml +1 -0
- data/.rubocop.yml +65 -0
- data/.rubocop_todo.yml +27 -0
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +4 -9
- data/Gemfile +29 -0
- data/README.md +110 -106
- data/RELEASE.md +306 -1
- data/Rakefile +52 -45
- data/gemfiles/Gemfile.minitest.latest +1 -0
- data/gemfiles/Gemfile.test-unit.latest +2 -5
- data/lib/mocha/any_instance_method.rb +9 -62
- data/lib/mocha/api.rb +84 -68
- data/lib/mocha/argument_iterator.rb +4 -8
- data/lib/mocha/backtrace_filter.rb +1 -5
- data/lib/mocha/block_matcher.rb +31 -0
- data/lib/mocha/cardinality.rb +60 -49
- data/lib/mocha/central.rb +21 -12
- data/lib/mocha/change_state_side_effect.rb +0 -4
- data/lib/mocha/class_methods.rb +19 -21
- data/lib/mocha/configuration.rb +312 -47
- data/lib/mocha/debug.rb +3 -2
- data/lib/mocha/deprecation.rb +8 -11
- data/lib/mocha/detection/mini_test.rb +0 -2
- data/lib/mocha/detection/test_unit.rb +3 -5
- data/lib/mocha/error_with_filtered_backtrace.rb +13 -0
- data/lib/mocha/exception_raiser.rb +4 -6
- data/lib/mocha/expectation.rb +186 -95
- data/lib/mocha/expectation_error.rb +1 -1
- data/lib/mocha/expectation_error_factory.rb +0 -1
- data/lib/mocha/expectation_list.rb +7 -11
- data/lib/mocha/hooks.rb +1 -3
- data/lib/mocha/in_state_ordering_constraint.rb +0 -4
- data/lib/mocha/inspect.rb +30 -38
- data/lib/mocha/instance_method.rb +11 -8
- data/lib/mocha/integration/mini_test/adapter.rb +2 -4
- data/lib/mocha/integration/mini_test/exception_translation.rb +1 -1
- data/lib/mocha/integration/mini_test.rb +10 -31
- data/lib/mocha/integration/monkey_patcher.rb +5 -7
- data/lib/mocha/integration/test_unit/adapter.rb +5 -6
- data/lib/mocha/integration/test_unit.rb +10 -26
- data/lib/mocha/invocation.rb +73 -0
- data/lib/mocha/is_a.rb +0 -2
- data/lib/mocha/logger.rb +0 -4
- data/lib/mocha/macos_version.rb +5 -0
- data/lib/mocha/method_matcher.rb +1 -5
- data/lib/mocha/minitest.rb +6 -0
- data/lib/mocha/mock.rb +99 -51
- data/lib/mocha/mockery.rb +70 -99
- data/lib/mocha/names.rb +2 -12
- data/lib/mocha/not_initialized_error.rb +7 -0
- data/lib/mocha/object_methods.rb +25 -31
- data/lib/mocha/parameter_matchers/all_of.rb +2 -8
- data/lib/mocha/parameter_matchers/any_of.rb +2 -8
- data/lib/mocha/parameter_matchers/any_parameters.rb +3 -9
- data/lib/mocha/parameter_matchers/anything.rb +2 -8
- data/lib/mocha/parameter_matchers/base.rb +7 -13
- data/lib/mocha/parameter_matchers/equals.rb +0 -6
- data/lib/mocha/parameter_matchers/{query_string.rb → equivalent_uri.rb} +14 -15
- data/lib/mocha/parameter_matchers/has_entries.rb +2 -7
- data/lib/mocha/parameter_matchers/has_entry.rb +26 -21
- data/lib/mocha/parameter_matchers/has_key.rb +2 -7
- data/lib/mocha/parameter_matchers/has_keys.rb +53 -0
- data/lib/mocha/parameter_matchers/has_value.rb +2 -7
- data/lib/mocha/parameter_matchers/includes.rb +6 -7
- data/lib/mocha/parameter_matchers/instance_methods.rb +27 -0
- data/lib/mocha/parameter_matchers/instance_of.rb +0 -6
- data/lib/mocha/parameter_matchers/is_a.rb +2 -7
- data/lib/mocha/parameter_matchers/kind_of.rb +2 -6
- data/lib/mocha/parameter_matchers/not.rb +2 -7
- data/lib/mocha/parameter_matchers/optionally.rb +4 -10
- data/lib/mocha/parameter_matchers/positional_or_keyword_hash.rb +64 -0
- data/lib/mocha/parameter_matchers/regexp_matches.rb +0 -6
- data/lib/mocha/parameter_matchers/responds_with.rb +3 -8
- data/lib/mocha/parameter_matchers/yaml_equivalent.rb +2 -6
- data/lib/mocha/parameter_matchers.rb +3 -4
- data/lib/mocha/parameters_matcher.rb +8 -11
- data/lib/mocha/raised_exception.rb +11 -0
- data/lib/mocha/receivers.rb +10 -14
- data/lib/mocha/return_values.rb +4 -8
- data/lib/mocha/ruby_version.rb +1 -2
- data/lib/mocha/sequence.rb +4 -9
- data/lib/mocha/single_return_value.rb +2 -5
- data/lib/mocha/state_machine.rb +33 -46
- data/lib/mocha/stubbed_method.rb +88 -0
- data/lib/mocha/stubbing_error.rb +2 -13
- data/lib/mocha/test_unit.rb +5 -2
- data/lib/mocha/thrower.rb +4 -6
- data/lib/mocha/thrown_object.rb +12 -0
- data/lib/mocha/version.rb +1 -1
- data/lib/mocha/yield_parameters.rb +7 -17
- data/mocha.gemspec +14 -65
- data/yard-templates/default/layout/html/google_analytics.erb +6 -9
- data/yard-templates/default/layout/html/setup.rb +2 -3
- metadata +26 -266
- data/bin/build-matrix +0 -70
- 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/init.rb +0 -3
- data/lib/mocha/class_method.rb +0 -119
- data/lib/mocha/integration/mini_test/nothing.rb +0 -19
- data/lib/mocha/integration/mini_test/version_13.rb +0 -51
- data/lib/mocha/integration/mini_test/version_140.rb +0 -51
- data/lib/mocha/integration/mini_test/version_141.rb +0 -62
- data/lib/mocha/integration/mini_test/version_142_to_172.rb +0 -62
- data/lib/mocha/integration/mini_test/version_200.rb +0 -63
- data/lib/mocha/integration/mini_test/version_201_to_222.rb +0 -63
- data/lib/mocha/integration/mini_test/version_2110_to_2111.rb +0 -67
- data/lib/mocha/integration/mini_test/version_2112_to_320.rb +0 -70
- data/lib/mocha/integration/mini_test/version_230_to_2101.rb +0 -65
- data/lib/mocha/integration/test_unit/gem_version_200.rb +0 -59
- data/lib/mocha/integration/test_unit/gem_version_201_to_202.rb +0 -59
- data/lib/mocha/integration/test_unit/gem_version_203_to_220.rb +0 -59
- data/lib/mocha/integration/test_unit/gem_version_230_to_250.rb +0 -65
- data/lib/mocha/integration/test_unit/nothing.rb +0 -19
- data/lib/mocha/integration/test_unit/ruby_version_185_and_below.rb +0 -58
- data/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb +0 -60
- data/lib/mocha/integration.rb +0 -14
- data/lib/mocha/mini_test.rb +0 -3
- data/lib/mocha/module_method.rb +0 -16
- data/lib/mocha/module_methods.rb +0 -14
- data/lib/mocha/multiple_yields.rb +0 -20
- data/lib/mocha/no_yields.rb +0 -11
- data/lib/mocha/parameter_matchers/object.rb +0 -17
- data/lib/mocha/pretty_parameters.rb +0 -28
- data/lib/mocha/setup.rb +0 -9
- data/lib/mocha/single_yield.rb +0 -18
- data/lib/mocha/standalone.rb +0 -4
- data/lib/mocha/unexpected_invocation.rb +0 -26
- data/lib/mocha_standalone.rb +0 -4
- data/test/acceptance/acceptance_test_helper.rb +0 -41
- data/test/acceptance/bug_18914_test.rb +0 -43
- data/test/acceptance/bug_21465_test.rb +0 -34
- data/test/acceptance/bug_21563_test.rb +0 -25
- data/test/acceptance/exception_rescue_test.rb +0 -55
- data/test/acceptance/expectations_on_multiple_methods_test.rb +0 -55
- data/test/acceptance/expected_invocation_count_test.rb +0 -232
- data/test/acceptance/failure_messages_test.rb +0 -64
- data/test/acceptance/issue_272_test.rb +0 -52
- data/test/acceptance/issue_65_test.rb +0 -63
- data/test/acceptance/issue_70_test.rb +0 -55
- data/test/acceptance/mocha_example_test.rb +0 -98
- data/test/acceptance/mocha_test_result_test.rb +0 -84
- data/test/acceptance/mock_test.rb +0 -100
- data/test/acceptance/mock_with_initializer_block_test.rb +0 -51
- data/test/acceptance/mocked_methods_dispatch_test.rb +0 -78
- data/test/acceptance/multiple_expectations_failure_message_test.rb +0 -68
- data/test/acceptance/optional_parameters_test.rb +0 -70
- data/test/acceptance/parameter_matcher_test.rb +0 -337
- data/test/acceptance/partial_mocks_test.rb +0 -47
- data/test/acceptance/prepend_test.rb +0 -89
- data/test/acceptance/raise_exception_test.rb +0 -39
- data/test/acceptance/return_value_test.rb +0 -52
- data/test/acceptance/sequence_test.rb +0 -192
- data/test/acceptance/states_test.rb +0 -70
- data/test/acceptance/stub_any_instance_method_defined_on_superclass_test.rb +0 -34
- data/test/acceptance/stub_any_instance_method_test.rb +0 -280
- 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 -78
- data/test/acceptance/stub_class_method_defined_on_module_test.rb +0 -75
- data/test/acceptance/stub_class_method_defined_on_superclass_test.rb +0 -112
- data/test/acceptance/stub_everything_test.rb +0 -56
- data/test/acceptance/stub_instance_method_defined_on_active_record_association_proxy_test.rb +0 -93
- data/test/acceptance/stub_instance_method_defined_on_class_and_aliased_test.rb +0 -69
- data/test/acceptance/stub_instance_method_defined_on_class_test.rb +0 -69
- data/test/acceptance/stub_instance_method_defined_on_kernel_module_test.rb +0 -75
- data/test/acceptance/stub_instance_method_defined_on_module_test.rb +0 -78
- data/test/acceptance/stub_instance_method_defined_on_object_class_test.rb +0 -75
- data/test/acceptance/stub_instance_method_defined_on_singleton_class_test.rb +0 -70
- data/test/acceptance/stub_instance_method_defined_on_superclass_test.rb +0 -72
- data/test/acceptance/stub_method_defined_on_module_and_aliased_test.rb +0 -39
- data/test/acceptance/stub_module_method_test.rb +0 -163
- data/test/acceptance/stub_test.rb +0 -52
- data/test/acceptance/stubba_example_test.rb +0 -102
- data/test/acceptance/stubba_test_result_test.rb +0 -66
- data/test/acceptance/stubbing_error_backtrace_test.rb +0 -64
- data/test/acceptance/stubbing_frozen_object_test.rb +0 -88
- data/test/acceptance/stubbing_method_accepting_block_parameter_test.rb +0 -48
- data/test/acceptance/stubbing_method_unnecessarily_test.rb +0 -65
- data/test/acceptance/stubbing_nil_test.rb +0 -61
- data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +0 -143
- data/test/acceptance/stubbing_non_existent_class_method_test.rb +0 -157
- data/test/acceptance/stubbing_non_existent_instance_method_test.rb +0 -147
- data/test/acceptance/stubbing_non_public_any_instance_method_test.rb +0 -130
- data/test/acceptance/stubbing_non_public_class_method_test.rb +0 -163
- data/test/acceptance/stubbing_non_public_instance_method_test.rb +0 -143
- data/test/acceptance/stubbing_on_non_mock_object_test.rb +0 -64
- data/test/acceptance/stubbing_same_class_method_on_parent_and_child_classes_test.rb +0 -35
- data/test/acceptance/throw_test.rb +0 -45
- data/test/acceptance/unexpected_invocation_test.rb +0 -25
- data/test/acceptance/unstubbing_test.rb +0 -168
- 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 -174
- data/test/integration/test_unit_test.rb +0 -8
- data/test/method_definer.rb +0 -24
- data/test/mini_test_result.rb +0 -90
- data/test/minitest_result.rb +0 -49
- data/test/simple_counter.rb +0 -13
- data/test/test_helper.rb +0 -50
- data/test/test_runner.rb +0 -58
- data/test/test_unit_result.rb +0 -20
- data/test/unit/any_instance_method_test.rb +0 -134
- data/test/unit/array_inspect_test.rb +0 -16
- data/test/unit/backtrace_filter_test.rb +0 -19
- data/test/unit/cardinality_test.rb +0 -56
- data/test/unit/central_test.rb +0 -100
- data/test/unit/change_state_side_effect_test.rb +0 -41
- data/test/unit/class_method_test.rb +0 -225
- data/test/unit/class_methods_test.rb +0 -40
- data/test/unit/configuration_test.rb +0 -38
- data/test/unit/date_time_inspect_test.rb +0 -21
- data/test/unit/exception_raiser_test.rb +0 -42
- data/test/unit/expectation_list_test.rb +0 -82
- data/test/unit/expectation_test.rb +0 -497
- data/test/unit/hash_inspect_test.rb +0 -16
- data/test/unit/hooks_test.rb +0 -29
- data/test/unit/in_state_ordering_constraint_test.rb +0 -43
- data/test/unit/method_matcher_test.rb +0 -28
- data/test/unit/mock_test.rb +0 -342
- data/test/unit/mockery_test.rb +0 -151
- data/test/unit/module_methods_test.rb +0 -19
- data/test/unit/multiple_yields_test.rb +0 -18
- data/test/unit/no_yields_test.rb +0 -18
- data/test/unit/object_inspect_test.rb +0 -39
- data/test/unit/object_methods_test.rb +0 -46
- data/test/unit/parameter_matchers/all_of_test.rb +0 -26
- data/test/unit/parameter_matchers/any_of_test.rb +0 -26
- data/test/unit/parameter_matchers/anything_test.rb +0 -21
- data/test/unit/parameter_matchers/equals_test.rb +0 -25
- data/test/unit/parameter_matchers/has_entries_test.rb +0 -51
- data/test/unit/parameter_matchers/has_entry_test.rb +0 -129
- data/test/unit/parameter_matchers/has_key_test.rb +0 -55
- data/test/unit/parameter_matchers/has_value_test.rb +0 -57
- data/test/unit/parameter_matchers/includes_test.rb +0 -102
- data/test/unit/parameter_matchers/instance_of_test.rb +0 -25
- data/test/unit/parameter_matchers/is_a_test.rb +0 -25
- data/test/unit/parameter_matchers/kind_of_test.rb +0 -25
- data/test/unit/parameter_matchers/not_test.rb +0 -26
- data/test/unit/parameter_matchers/regexp_matches_test.rb +0 -46
- data/test/unit/parameter_matchers/responds_with_test.rb +0 -32
- data/test/unit/parameter_matchers/stub_matcher.rb +0 -27
- data/test/unit/parameter_matchers/yaml_equivalent_test.rb +0 -25
- data/test/unit/parameters_matcher_test.rb +0 -121
- data/test/unit/receivers_test.rb +0 -66
- data/test/unit/return_values_test.rb +0 -63
- data/test/unit/sequence_test.rb +0 -104
- data/test/unit/single_return_value_test.rb +0 -14
- data/test/unit/single_yield_test.rb +0 -18
- data/test/unit/state_machine_test.rb +0 -98
- data/test/unit/string_inspect_test.rb +0 -11
- data/test/unit/thrower_test.rb +0 -20
- data/test/unit/yield_parameters_test.rb +0 -93
data/lib/mocha/expectation.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ruby2_keywords'
|
1
2
|
require 'mocha/method_matcher'
|
2
3
|
require 'mocha/parameters_matcher'
|
3
4
|
require 'mocha/expectation_error'
|
@@ -9,12 +10,13 @@ require 'mocha/is_a'
|
|
9
10
|
require 'mocha/in_state_ordering_constraint'
|
10
11
|
require 'mocha/change_state_side_effect'
|
11
12
|
require 'mocha/cardinality'
|
13
|
+
require 'mocha/configuration'
|
14
|
+
require 'mocha/block_matcher'
|
15
|
+
require 'mocha/backtrace_filter'
|
12
16
|
|
13
17
|
module Mocha
|
14
|
-
|
15
18
|
# Methods on expectations returned from {Mock#expects}, {Mock#stubs}, {ObjectMethods#expects} and {ObjectMethods#stubs}.
|
16
19
|
class Expectation
|
17
|
-
|
18
20
|
# Modifies expectation so that the number of calls to the expected method must be within a specific +range+.
|
19
21
|
#
|
20
22
|
# @param [Range,Integer] range specifies the allowable range in the number of expected invocations.
|
@@ -42,7 +44,7 @@ module Mocha
|
|
42
44
|
# object.expected_method
|
43
45
|
# # => verify fails
|
44
46
|
def times(range)
|
45
|
-
@cardinality
|
47
|
+
@cardinality.times(range)
|
46
48
|
self
|
47
49
|
end
|
48
50
|
|
@@ -68,7 +70,7 @@ module Mocha
|
|
68
70
|
# object.expected_method
|
69
71
|
# # => verify fails
|
70
72
|
def twice
|
71
|
-
@cardinality
|
73
|
+
@cardinality.exactly(2)
|
72
74
|
self
|
73
75
|
end
|
74
76
|
|
@@ -93,7 +95,7 @@ module Mocha
|
|
93
95
|
# object.expects(:expected_method).once
|
94
96
|
# # => verify fails
|
95
97
|
def once
|
96
|
-
@cardinality
|
98
|
+
@cardinality.exactly(1)
|
97
99
|
self
|
98
100
|
end
|
99
101
|
|
@@ -110,7 +112,7 @@ module Mocha
|
|
110
112
|
# object.expects(:expected_method).never
|
111
113
|
# # => verify succeeds
|
112
114
|
def never
|
113
|
-
@cardinality
|
115
|
+
@cardinality.exactly(0)
|
114
116
|
self
|
115
117
|
end
|
116
118
|
|
@@ -130,7 +132,7 @@ module Mocha
|
|
130
132
|
# object.expected_method
|
131
133
|
# # => verify fails
|
132
134
|
def at_least(minimum_number_of_times)
|
133
|
-
@cardinality
|
135
|
+
@cardinality.at_least(minimum_number_of_times)
|
134
136
|
self
|
135
137
|
end
|
136
138
|
|
@@ -149,7 +151,6 @@ module Mocha
|
|
149
151
|
# # => verify fails
|
150
152
|
def at_least_once
|
151
153
|
at_least(1)
|
152
|
-
self
|
153
154
|
end
|
154
155
|
|
155
156
|
# Modifies expectation so that the expected method must be called at most a +maximum_number_of_times+.
|
@@ -167,7 +168,7 @@ module Mocha
|
|
167
168
|
# object.expects(:expected_method).at_most(2)
|
168
169
|
# 3.times { object.expected_method } # => unexpected invocation
|
169
170
|
def at_most(maximum_number_of_times)
|
170
|
-
@cardinality
|
171
|
+
@cardinality.at_most(maximum_number_of_times)
|
171
172
|
self
|
172
173
|
end
|
173
174
|
|
@@ -184,22 +185,30 @@ module Mocha
|
|
184
185
|
# object = mock()
|
185
186
|
# object.expects(:expected_method).at_most_once
|
186
187
|
# 2.times { object.expected_method } # => unexpected invocation
|
187
|
-
def at_most_once
|
188
|
+
def at_most_once
|
188
189
|
at_most(1)
|
189
|
-
self
|
190
190
|
end
|
191
191
|
|
192
|
-
# Modifies expectation so that the expected method must be called with +
|
192
|
+
# Modifies expectation so that the expected method must be called with +expected_parameters_or_matchers+.
|
193
|
+
#
|
194
|
+
# May be used with Ruby literals or variables for exact matching or with parameter matchers for less-specific matching, e.g. {ParameterMatchers#includes}, {ParameterMatchers#has_key}, etc. See {ParameterMatchers} for a list of all available parameter matchers.
|
195
|
+
#
|
196
|
+
# Positional arguments were separated from keyword arguments in Ruby v3 (see {https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0 this article}). In relation to this a new configuration option ({Configuration#strict_keyword_argument_matching=}) is available in Ruby >= 2.7.
|
197
|
+
#
|
198
|
+
# When {Configuration#strict_keyword_argument_matching=} is set to +false+ (which is currently the default), a positional +Hash+ and a set of keyword arguments passed to {#with} are treated the same for the purposes of parameter matching. However, a deprecation warning will be displayed if a positional +Hash+ matches a set of keyword arguments or vice versa. This is because {Configuration#strict_keyword_argument_matching=} will default to +true+ in the future.
|
199
|
+
#
|
200
|
+
# When {Configuration#strict_keyword_argument_matching=} is set to +true+, an actual positional +Hash+ will not match an expected set of keyword arguments; and vice versa, an actual set of keyword arguments will not match an expected positional +Hash+, i.e. the parameter matching is stricter.
|
193
201
|
#
|
194
|
-
#
|
202
|
+
# @see ParameterMatchers
|
203
|
+
# @see Configuration#strict_keyword_argument_matching=
|
195
204
|
#
|
196
|
-
# @param [*Array]
|
205
|
+
# @param [*Array<Object,ParameterMatchers::Base>] expected_parameters_or_matchers expected parameter values or parameter matchers.
|
197
206
|
# @yield optional block specifying custom matching.
|
198
|
-
# @yieldparam [*Array] actual_parameters parameters with which expected method was invoked.
|
207
|
+
# @yieldparam [*Array<Object>] actual_parameters parameters with which expected method was invoked.
|
199
208
|
# @yieldreturn [Boolean] +true+ if +actual_parameters+ are acceptable.
|
200
209
|
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
201
210
|
#
|
202
|
-
# @example Expected method must be called with
|
211
|
+
# @example Expected method must be called with exact parameter values.
|
203
212
|
# object = mock()
|
204
213
|
# object.expects(:expected_method).with(:param1, :param2)
|
205
214
|
# object.expected_method(:param1, :param2)
|
@@ -210,6 +219,43 @@ module Mocha
|
|
210
219
|
# object.expected_method(:param3)
|
211
220
|
# # => verify fails
|
212
221
|
#
|
222
|
+
# @example Expected method must be called with parameters matching parameter matchers.
|
223
|
+
# object = mock()
|
224
|
+
# object.expects(:expected_method).with(includes('string2'), anything)
|
225
|
+
# object.expected_method(['string1', 'string2'], 'any-old-value')
|
226
|
+
# # => verify succeeds
|
227
|
+
#
|
228
|
+
# object = mock()
|
229
|
+
# object.expects(:expected_method).with(includes('string2'), anything)
|
230
|
+
# object.expected_method(['string1'], 'any-old-value')
|
231
|
+
# # => verify fails
|
232
|
+
#
|
233
|
+
# @example Loose keyword argument matching (default)
|
234
|
+
#
|
235
|
+
# class Example
|
236
|
+
# def foo(a, bar:); end
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# example = Example.new
|
240
|
+
# example.expects(:foo).with('a', bar: 'b')
|
241
|
+
# example.foo('a', { bar: 'b' })
|
242
|
+
# # This passes the test, but would result in an ArgumentError in practice
|
243
|
+
#
|
244
|
+
# @example Strict keyword argument matching
|
245
|
+
#
|
246
|
+
# Mocha.configure do |c|
|
247
|
+
# c.strict_keyword_argument_matching = true
|
248
|
+
# end
|
249
|
+
#
|
250
|
+
# class Example
|
251
|
+
# def foo(a, bar:); end
|
252
|
+
# end
|
253
|
+
#
|
254
|
+
# example = Example.new
|
255
|
+
# example.expects(:foo).with('a', bar: 'b')
|
256
|
+
# example.foo('a', { bar: 'b' })
|
257
|
+
# # This now fails as expected
|
258
|
+
#
|
213
259
|
# @example Expected method must be called with a value divisible by 4.
|
214
260
|
# object = mock()
|
215
261
|
# object.expects(:expected_method).with() { |value| value % 4 == 0 }
|
@@ -220,12 +266,55 @@ module Mocha
|
|
220
266
|
# object.expects(:expected_method).with() { |value| value % 4 == 0 }
|
221
267
|
# object.expected_method(17)
|
222
268
|
# # => verify fails
|
223
|
-
def with(*
|
224
|
-
@parameters_matcher = ParametersMatcher.new(
|
269
|
+
def with(*expected_parameters_or_matchers, &matching_block)
|
270
|
+
@parameters_matcher = ParametersMatcher.new(expected_parameters_or_matchers, self, &matching_block)
|
271
|
+
self
|
272
|
+
end
|
273
|
+
ruby2_keywords(:with)
|
274
|
+
|
275
|
+
# Modifies expectation so that the expected method must be called with a block.
|
276
|
+
#
|
277
|
+
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
278
|
+
#
|
279
|
+
# @example Expected method must be called with a block.
|
280
|
+
# object = mock()
|
281
|
+
# object.expects(:expected_method).with_block_given
|
282
|
+
# object.expected_method { 1 + 1 }
|
283
|
+
# # => verify succeeds
|
284
|
+
#
|
285
|
+
# object = mock()
|
286
|
+
# object.expects(:expected_method).with_block_given
|
287
|
+
# object.expected_method
|
288
|
+
# # => verify fails
|
289
|
+
def with_block_given
|
290
|
+
@block_matcher = BlockMatchers::BlockGiven.new
|
291
|
+
self
|
292
|
+
end
|
293
|
+
|
294
|
+
# Modifies expectation so that the expected method must be called without a block.
|
295
|
+
#
|
296
|
+
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
297
|
+
#
|
298
|
+
# @example Expected method must be called without a block.
|
299
|
+
# object = mock()
|
300
|
+
# object.expects(:expected_method).with_no_block_given
|
301
|
+
# object.expected_method
|
302
|
+
# # => verify succeeds
|
303
|
+
#
|
304
|
+
# object = mock()
|
305
|
+
# object.expects(:expected_method).with_block_given
|
306
|
+
# object.expected_method { 1 + 1 }
|
307
|
+
# # => verify fails
|
308
|
+
def with_no_block_given
|
309
|
+
@block_matcher = BlockMatchers::NoBlockGiven.new
|
225
310
|
self
|
226
311
|
end
|
227
312
|
|
228
|
-
# Modifies expectation so that when the expected method is called, it yields with the specified +parameters+.
|
313
|
+
# Modifies expectation so that when the expected method is called, it yields to the block with the specified +parameters+.
|
314
|
+
#
|
315
|
+
# If no +parameters+ are specified, it yields to the block without any parameters.
|
316
|
+
#
|
317
|
+
# If no block is provided, the method will still attempt to yield resulting in a +LocalJumpError+. Note that this is what would happen if a "real" (non-mock) method implementation tried to yield to a non-existent block.
|
229
318
|
#
|
230
319
|
# May be called multiple times on the same expectation for consecutive invocations.
|
231
320
|
#
|
@@ -233,51 +322,58 @@ module Mocha
|
|
233
322
|
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
234
323
|
# @see #then
|
235
324
|
#
|
325
|
+
# @example Yield when expected method is invoked.
|
326
|
+
# benchmark = mock()
|
327
|
+
# benchmark.expects(:measure).yields
|
328
|
+
# yielded = false
|
329
|
+
# benchmark.measure { yielded = true }
|
330
|
+
# yielded # => true
|
331
|
+
#
|
236
332
|
# @example Yield parameters when expected method is invoked.
|
237
|
-
#
|
238
|
-
#
|
239
|
-
#
|
240
|
-
#
|
241
|
-
#
|
333
|
+
# fibonacci = mock()
|
334
|
+
# fibonacci.expects(:next_pair).yields(0, 1)
|
335
|
+
# sum = 0
|
336
|
+
# fibonacci.next_pair { |first, second| sum = first + second }
|
337
|
+
# sum # => 1
|
242
338
|
#
|
243
339
|
# @example Yield different parameters on different invocations of the expected method.
|
244
|
-
#
|
245
|
-
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
#
|
251
|
-
# yielded_values_from_second_invocation # => [2]
|
340
|
+
# fibonacci = mock()
|
341
|
+
# fibonacci.expects(:next_pair).yields(0, 1).then.yields(1, 1)
|
342
|
+
# sum = 0
|
343
|
+
# fibonacci.next_pair { |first, second| sum = first + second }
|
344
|
+
# sum # => 1
|
345
|
+
# fibonacci.next_pair { |first, second| sum = first + second }
|
346
|
+
# sum # => 2
|
252
347
|
def yields(*parameters)
|
253
|
-
|
254
|
-
self
|
348
|
+
multiple_yields(parameters)
|
255
349
|
end
|
256
350
|
|
257
351
|
# Modifies expectation so that when the expected method is called, it yields multiple times per invocation with the specified +parameter_groups+.
|
258
352
|
#
|
259
|
-
#
|
353
|
+
# If no block is provided, the method will still attempt to yield resulting in a +LocalJumpError+. Note that this is what would happen if a "real" (non-mock) method implementation tried to yield to a non-existent block.
|
354
|
+
#
|
355
|
+
# @param [*Array<Array>] parameter_groups each element of +parameter_groups+ should iself be an +Array+ representing the parameters to be passed to the block for a single yield. Any element of +parameter_groups+ that is not an +Array+ is wrapped in an +Array+.
|
260
356
|
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
261
357
|
# @see #then
|
262
358
|
#
|
263
|
-
# @example When
|
264
|
-
#
|
265
|
-
#
|
266
|
-
#
|
267
|
-
#
|
268
|
-
#
|
269
|
-
#
|
270
|
-
# @example Yield different groups of parameters on different invocations of the expected method.
|
271
|
-
#
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
#
|
276
|
-
#
|
277
|
-
#
|
278
|
-
#
|
359
|
+
# @example When +foreach+ is called, the stub will invoke the block twice, the first time it passes ['row1_col1', 'row1_col2'] as the parameters, and the second time it passes ['row2_col1', ''] as the parameters.
|
360
|
+
# csv = mock()
|
361
|
+
# csv.expects(:foreach).with("path/to/file.csv").multiple_yields(['row1_col1', 'row1_col2'], ['row2_col1', ''])
|
362
|
+
# rows = []
|
363
|
+
# csv.foreach { |row| rows << row }
|
364
|
+
# rows # => [['row1_col1', 'row1_col2'], ['row2_col1', '']]
|
365
|
+
#
|
366
|
+
# @example Yield different groups of parameters on different invocations of the expected method. Simulating a situation where the CSV file at 'path/to/file.csv' has been modified between the two calls to +foreach+.
|
367
|
+
# csv = mock()
|
368
|
+
# csv.stubs(:foreach).with("path/to/file.csv").multiple_yields(['old_row1_col1', 'old_row1_col2'], ['old_row2_col1', '']).then.multiple_yields(['new_row1_col1', ''], ['new_row2_col1', 'new_row2_col2'])
|
369
|
+
# rows_from_first_invocation = []
|
370
|
+
# rows_from_second_invocation = []
|
371
|
+
# csv.foreach { |row| rows_from_first_invocation << row } # first invocation
|
372
|
+
# csv.foreach { |row| rows_from_second_invocation << row } # second invocation
|
373
|
+
# rows_from_first_invocation # => [['old_row1_col1', 'old_row1_col2'], ['old_row2_col1', '']]
|
374
|
+
# rows_from_second_invocation # => [['new_row1_col1', ''], ['new_row2_col1', 'new_row2_col2']]
|
279
375
|
def multiple_yields(*parameter_groups)
|
280
|
-
@yield_parameters.
|
376
|
+
@yield_parameters.add(*parameter_groups)
|
281
377
|
self
|
282
378
|
end
|
283
379
|
|
@@ -409,9 +505,9 @@ module Mocha
|
|
409
505
|
|
410
506
|
# @overload def then
|
411
507
|
# Used as syntactic sugar to improve readability. It has no effect on state of the expectation.
|
412
|
-
# @overload def then(
|
413
|
-
# Used to change the +state_machine+ to the
|
414
|
-
# @param [StateMachine::State] state_machine.is(state_name) provides a mechanism to change the +state_machine+ into the state specified by +state_name+ when the expected method is invoked.
|
508
|
+
# @overload def then(state)
|
509
|
+
# Used to change the +state_machine+ to the specified state when the expected invocation occurs.
|
510
|
+
# @param [StateMachine::State] state state_machine.is(state_name) provides a mechanism to change the +state_machine+ into the state specified by +state_name+ when the expected method is invoked.
|
415
511
|
#
|
416
512
|
# @see API#states
|
417
513
|
# @see StateMachine
|
@@ -437,17 +533,14 @@ module Mocha
|
|
437
533
|
# radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
|
438
534
|
# radio.expects(:adjust_volume).with(-5).when(power.is('on'))
|
439
535
|
# radio.expects(:switch_off).then(power.is('off'))
|
440
|
-
def then(
|
441
|
-
|
442
|
-
state = parameters.first
|
443
|
-
add_side_effect(ChangeStateSideEffect.new(state))
|
444
|
-
end
|
536
|
+
def then(state = nil)
|
537
|
+
add_side_effect(ChangeStateSideEffect.new(state)) if state
|
445
538
|
self
|
446
539
|
end
|
447
540
|
|
448
|
-
# Constrains the expectation to occur only when the +state_machine+ is in the state specified by +
|
541
|
+
# Constrains the expectation to occur only when the +state_machine+ is in the state specified by +state_predicate+.
|
449
542
|
#
|
450
|
-
# @param [StateMachine::StatePredicate] state_machine.is(state_name) provides a mechanism to determine whether the +state_machine+ is in the state specified by +
|
543
|
+
# @param [StateMachine::StatePredicate] state_predicate +state_machine.is(state_name)+ provides a mechanism to determine whether the +state_machine+ is in the state specified by +state_predicate+ when the expected method is invoked.
|
451
544
|
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
452
545
|
#
|
453
546
|
# @see API#states
|
@@ -479,7 +572,8 @@ module Mocha
|
|
479
572
|
#
|
480
573
|
# An expected method can appear in multiple sequences.
|
481
574
|
#
|
482
|
-
# @param [
|
575
|
+
# @param [Sequence] sequence sequence in which expected method should appear.
|
576
|
+
# @param [*Array<Sequence>] sequences more sequences in which expected method should appear.
|
483
577
|
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
484
578
|
#
|
485
579
|
# @see API#sequence
|
@@ -491,8 +585,8 @@ module Mocha
|
|
491
585
|
# egg.expects(:crack).in_sequence(breakfast)
|
492
586
|
# egg.expects(:fry).in_sequence(breakfast)
|
493
587
|
# egg.expects(:eat).in_sequence(breakfast)
|
494
|
-
def in_sequence(*sequences)
|
495
|
-
sequences.each { |
|
588
|
+
def in_sequence(sequence, *sequences)
|
589
|
+
sequences.unshift(sequence).each { |seq| add_in_sequence_ordering_constraint(seq) }
|
496
590
|
self
|
497
591
|
end
|
498
592
|
|
@@ -504,9 +598,10 @@ module Mocha
|
|
504
598
|
@mock = mock
|
505
599
|
@method_matcher = MethodMatcher.new(expected_method_name.to_sym)
|
506
600
|
@parameters_matcher = ParametersMatcher.new
|
601
|
+
@block_matcher = BlockMatchers::OptionalBlock.new
|
507
602
|
@ordering_constraints = []
|
508
603
|
@side_effects = []
|
509
|
-
@cardinality
|
604
|
+
@cardinality = Cardinality.new.exactly(1)
|
510
605
|
@return_values = ReturnValues.new
|
511
606
|
@yield_parameters = YieldParameters.new
|
512
607
|
@backtrace = backtrace || caller
|
@@ -529,12 +624,12 @@ module Mocha
|
|
529
624
|
|
530
625
|
# @private
|
531
626
|
def perform_side_effects
|
532
|
-
@side_effects.each
|
627
|
+
@side_effects.each(&:perform)
|
533
628
|
end
|
534
629
|
|
535
630
|
# @private
|
536
631
|
def in_correct_order?
|
537
|
-
@ordering_constraints.all?
|
632
|
+
@ordering_constraints.all?(&:allows_invocation_now?)
|
538
633
|
end
|
539
634
|
|
540
635
|
# @private
|
@@ -543,70 +638,66 @@ module Mocha
|
|
543
638
|
end
|
544
639
|
|
545
640
|
# @private
|
546
|
-
def match?(
|
547
|
-
@method_matcher.match?(
|
641
|
+
def match?(invocation)
|
642
|
+
@method_matcher.match?(invocation.method_name) && @parameters_matcher.match?(invocation.arguments) && @block_matcher.match?(invocation.block) && in_correct_order?
|
548
643
|
end
|
549
644
|
|
550
645
|
# @private
|
551
646
|
def invocations_allowed?
|
552
|
-
@cardinality.invocations_allowed?
|
647
|
+
@cardinality.invocations_allowed?
|
553
648
|
end
|
554
649
|
|
555
650
|
# @private
|
556
651
|
def satisfied?
|
557
|
-
@cardinality.satisfied?
|
652
|
+
@cardinality.satisfied?
|
558
653
|
end
|
559
654
|
|
560
655
|
# @private
|
561
|
-
def invoke
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
@yield_parameters.next_invocation.each do |yield_parameters|
|
566
|
-
yield(*yield_parameters)
|
567
|
-
end
|
568
|
-
end
|
569
|
-
@return_values.next
|
656
|
+
def invoke(invocation)
|
657
|
+
perform_side_effects
|
658
|
+
@cardinality << invocation
|
659
|
+
invocation.call(@yield_parameters, @return_values)
|
570
660
|
end
|
571
661
|
|
572
662
|
# @private
|
573
663
|
def verified?(assertion_counter = nil)
|
574
664
|
assertion_counter.increment if assertion_counter && @cardinality.needs_verifying?
|
575
|
-
@cardinality.verified?
|
665
|
+
@cardinality.verified?
|
576
666
|
end
|
577
667
|
|
578
668
|
# @private
|
579
669
|
def used?
|
580
|
-
@cardinality.used?
|
670
|
+
@cardinality.used?
|
581
671
|
end
|
582
672
|
|
583
673
|
# @private
|
584
674
|
def inspect
|
585
675
|
address = __id__ * 2
|
586
676
|
address += 0x100000000 if address < 0
|
587
|
-
"#<Expectation:0x#{'%x'
|
677
|
+
"#<Expectation:0x#{format('%x', address)} #{mocha_inspect} >"
|
588
678
|
end
|
589
679
|
|
590
680
|
# @private
|
591
681
|
def mocha_inspect
|
592
|
-
message = "#{@cardinality.
|
593
|
-
message <<
|
594
|
-
|
595
|
-
|
596
|
-
when 2 then "invoked twice"
|
597
|
-
else "invoked #{@invocation_count} times"
|
682
|
+
message = "#{@cardinality.anticipated_times}, #{@cardinality.invoked_times}: #{method_signature}"
|
683
|
+
message << "; #{@ordering_constraints.map(&:mocha_inspect).join('; ')}" unless @ordering_constraints.empty?
|
684
|
+
if Mocha.configuration.display_matching_invocations_on_failure?
|
685
|
+
message << @cardinality.actual_invocations
|
598
686
|
end
|
599
|
-
message << ": "
|
600
|
-
message << method_signature
|
601
|
-
message << "; #{@ordering_constraints.map { |oc| oc.mocha_inspect }.join("; ")}" unless @ordering_constraints.empty?
|
602
687
|
message
|
603
688
|
end
|
604
689
|
|
605
690
|
# @private
|
606
691
|
def method_signature
|
607
|
-
"#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}"
|
692
|
+
signature = "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}"
|
693
|
+
signature << " #{@block_matcher.mocha_inspect}" if @block_matcher.mocha_inspect
|
694
|
+
signature
|
608
695
|
end
|
609
696
|
|
697
|
+
# @private
|
698
|
+
def definition_location
|
699
|
+
filter = BacktraceFilter.new
|
700
|
+
filter.filtered(backtrace)[0]
|
701
|
+
end
|
610
702
|
end
|
611
|
-
|
612
703
|
end
|
@@ -4,5 +4,5 @@ module Mocha
|
|
4
4
|
# Authors of test libraries may use +Mocha::ExpectationErrorFactory+ to have Mocha raise a different exception.
|
5
5
|
#
|
6
6
|
# @see Mocha::ExpectationErrorFactory
|
7
|
-
class ExpectationError < Exception; end
|
7
|
+
class ExpectationError < Exception; end # rubocop:disable Lint/InheritException
|
8
8
|
end
|
@@ -2,7 +2,6 @@ require 'mocha/backtrace_filter'
|
|
2
2
|
require 'mocha/expectation_error'
|
3
3
|
|
4
4
|
module Mocha
|
5
|
-
|
6
5
|
# This factory determines what class of exception should be raised when Mocha detects a test failure.
|
7
6
|
#
|
8
7
|
# This class should only be used by authors of test libraries and not by typical "users" of Mocha.
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class ExpectationList
|
4
|
-
|
5
3
|
def initialize(expectations = [])
|
6
4
|
@expectations = expectations
|
7
5
|
end
|
@@ -19,12 +17,12 @@ module Mocha
|
|
19
17
|
@expectations.any? { |expectation| expectation.matches_method?(method_name) }
|
20
18
|
end
|
21
19
|
|
22
|
-
def match(
|
23
|
-
matching_expectations(
|
20
|
+
def match(invocation)
|
21
|
+
matching_expectations(invocation).first
|
24
22
|
end
|
25
23
|
|
26
|
-
def match_allowing_invocation(
|
27
|
-
matching_expectations(
|
24
|
+
def match_allowing_invocation(invocation)
|
25
|
+
matching_expectations(invocation).detect(&:invocations_allowed?)
|
28
26
|
end
|
29
27
|
|
30
28
|
def verified?(assertion_counter = nil)
|
@@ -48,15 +46,13 @@ module Mocha
|
|
48
46
|
end
|
49
47
|
|
50
48
|
def +(other)
|
51
|
-
self.class.new(
|
49
|
+
self.class.new(to_a + other.to_a)
|
52
50
|
end
|
53
51
|
|
54
52
|
private
|
55
53
|
|
56
|
-
def matching_expectations(
|
57
|
-
@expectations.select { |e| e.match?(
|
54
|
+
def matching_expectations(invocation)
|
55
|
+
@expectations.select { |e| e.match?(invocation) }
|
58
56
|
end
|
59
|
-
|
60
57
|
end
|
61
|
-
|
62
58
|
end
|
data/lib/mocha/hooks.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'mocha/mockery'
|
2
2
|
|
3
3
|
module Mocha
|
4
|
-
|
5
4
|
# Integration hooks for test library authors.
|
6
5
|
#
|
7
6
|
# The methods in this module should be called from test libraries wishing to integrate with Mocha.
|
@@ -21,6 +20,7 @@ module Mocha
|
|
21
20
|
#
|
22
21
|
# This method should be called before each individual test starts (including before any "setup" code).
|
23
22
|
def mocha_setup
|
23
|
+
Mockery.setup
|
24
24
|
end
|
25
25
|
|
26
26
|
# Verifies that all mock expectations have been met (only for use by authors of test libraries).
|
@@ -37,8 +37,6 @@ module Mocha
|
|
37
37
|
# This method should be called after each individual test has finished (including after any "teardown" code).
|
38
38
|
def mocha_teardown
|
39
39
|
Mockery.teardown
|
40
|
-
ensure
|
41
|
-
Mockery.reset_instance
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class InStateOrderingConstraint
|
4
|
-
|
5
3
|
def initialize(state_predicate)
|
6
4
|
@state_predicate = state_predicate
|
7
5
|
end
|
@@ -13,7 +11,5 @@ module Mocha
|
|
13
11
|
def mocha_inspect
|
14
12
|
"when #{@state_predicate.mocha_inspect}"
|
15
13
|
end
|
16
|
-
|
17
14
|
end
|
18
|
-
|
19
15
|
end
|