mocha 1.4.0 → 2.1.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 +53 -0
- data/.rubocop_todo.yml +27 -0
- data/.yardopts +1 -1
- data/CONTRIBUTING.md +4 -9
- data/COPYING.md +2 -2
- data/Gemfile +27 -0
- data/MIT-LICENSE.md +1 -1
- data/README.md +88 -117
- data/RELEASE.md +340 -0
- data/Rakefile +53 -52
- 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 -74
- data/lib/mocha/argument_iterator.rb +4 -8
- data/lib/mocha/backtrace_filter.rb +3 -7
- 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 +317 -52
- data/lib/mocha/debug.rb +2 -4
- data/lib/mocha/deprecation.rb +6 -12
- 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 -28
- data/lib/mocha/instance_method.rb +14 -3
- data/lib/mocha/integration/mini_test/adapter.rb +3 -5
- 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 +8 -9
- 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 +5 -2
- data/lib/mocha/mock.rb +104 -68
- 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/equivalent_uri.rb +3 -13
- 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 +4 -6
- 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 +2 -3
- 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 +15 -65
- metadata +27 -257
- 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 -5
- 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 -58
- 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 -301
- 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 -201
- 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 -75
- 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 -76
- 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 -16
- data/test/execution_point.rb +0 -38
- 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 -136
- 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 -229
- 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 -350
- data/test/unit/mockery_test.rb +0 -157
- 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/equivalent_uri_test.rb +0 -51
- 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 -107
- 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/yard-templates/default/layout/html/google_analytics.erb +0 -11
- data/yard-templates/default/layout/html/setup.rb +0 -6
data/lib/mocha/mock.rb
CHANGED
@@ -1,22 +1,26 @@
|
|
1
|
-
require '
|
1
|
+
require 'ruby2_keywords'
|
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
|
-
require 'mocha/ruby_version'
|
13
11
|
|
14
12
|
module Mocha
|
15
|
-
|
16
13
|
# Traditional mock object.
|
17
14
|
#
|
18
|
-
#
|
19
|
-
# methods on {Expectation}.
|
15
|
+
# {expects} and {stubs} return an {Expectation} which can be further modified
|
16
|
+
# by methods on {Expectation}.
|
17
|
+
#
|
18
|
+
# {responds_like} and {responds_like_instance_of} both return a {Mock}, and
|
19
|
+
# can therefore, be chained to the original creation methods in {API}.
|
20
|
+
# They force the mock to indicate what it is supposed to be mocking, thus
|
21
|
+
# making it a safer verifying mock. They check that the underlying +responder+
|
22
|
+
# will actually respond to the methods being stubbed, throwing a
|
23
|
+
# +NoMethodError+ upon invocation otherwise.
|
20
24
|
#
|
21
25
|
# Stubs and expectations are basically the same thing. A stub is just an
|
22
26
|
# expectation of zero or more invocations. The {#stubs} method is syntactic
|
@@ -69,15 +73,14 @@ module Mocha
|
|
69
73
|
# different mock objects, use the {Expectation#in_sequence} method to
|
70
74
|
# explicitly define a total or partial ordering of invocations.
|
71
75
|
class Mock
|
72
|
-
|
73
76
|
# Adds an expectation that the specified method must be called exactly once with any parameters.
|
74
77
|
#
|
75
|
-
# @
|
76
|
-
# @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.
|
78
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
77
79
|
#
|
78
80
|
# @overload def expects(method_name)
|
81
|
+
# @param [Symbol,String] method_name name of expected method
|
79
82
|
# @overload def expects(expected_methods_vs_return_values)
|
80
|
-
#
|
83
|
+
# @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.
|
81
84
|
#
|
82
85
|
# @example Expected method invoked once so no error raised
|
83
86
|
# object = mock()
|
@@ -105,24 +108,26 @@ module Mocha
|
|
105
108
|
# object.expects(:expected_method_one).returns(:result_one)
|
106
109
|
# object.expects(:expected_method_two).returns(:result_two)
|
107
110
|
def expects(method_name_or_hash, backtrace = nil)
|
111
|
+
expectation = nil
|
108
112
|
iterator = ArgumentIterator.new(method_name_or_hash)
|
109
|
-
iterator.each
|
113
|
+
iterator.each do |*args|
|
110
114
|
method_name = args.shift
|
111
115
|
ensure_method_not_already_defined(method_name)
|
112
116
|
expectation = Expectation.new(self, method_name, backtrace)
|
113
|
-
expectation.returns(args.shift)
|
117
|
+
expectation.returns(args.shift) unless args.empty?
|
114
118
|
@expectations.add(expectation)
|
115
|
-
|
119
|
+
end
|
120
|
+
expectation
|
116
121
|
end
|
117
122
|
|
118
123
|
# Adds an expectation that the specified method may be called any number of times with any parameters.
|
119
124
|
#
|
120
|
-
# @
|
121
|
-
# @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.
|
125
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
122
126
|
#
|
123
127
|
# @overload def stubs(method_name)
|
128
|
+
# @param [Symbol,String] method_name name of stubbed method
|
124
129
|
# @overload def stubs(stubbed_methods_vs_return_values)
|
125
|
-
#
|
130
|
+
# @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.
|
126
131
|
#
|
127
132
|
# @example No error raised however many times stubbed method is invoked
|
128
133
|
# object = mock()
|
@@ -141,36 +146,48 @@ module Mocha
|
|
141
146
|
# object.stubs(:stubbed_method_one).returns(:result_one)
|
142
147
|
# object.stubs(:stubbed_method_two).returns(:result_two)
|
143
148
|
def stubs(method_name_or_hash, backtrace = nil)
|
149
|
+
expectation = nil
|
144
150
|
iterator = ArgumentIterator.new(method_name_or_hash)
|
145
|
-
iterator.each
|
151
|
+
iterator.each do |*args|
|
146
152
|
method_name = args.shift
|
147
153
|
ensure_method_not_already_defined(method_name)
|
148
154
|
expectation = Expectation.new(self, method_name, backtrace)
|
149
155
|
expectation.at_least(0)
|
150
|
-
expectation.returns(args.shift)
|
156
|
+
expectation.returns(args.shift) unless args.empty?
|
151
157
|
@expectations.add(expectation)
|
152
|
-
|
158
|
+
end
|
159
|
+
expectation
|
153
160
|
end
|
154
161
|
|
155
|
-
# Removes the specified stubbed
|
162
|
+
# Removes the specified stubbed methods (added by calls to {#expects} or {#stubs}) and all expectations associated with them.
|
156
163
|
#
|
157
|
-
# @param [Symbol]
|
164
|
+
# @param [Array<Symbol>] method_names names of methods to unstub.
|
158
165
|
#
|
159
166
|
# @example Invoking an unstubbed method causes error to be raised
|
160
|
-
# object = mock('mock')
|
167
|
+
# object = mock('mock')
|
161
168
|
# object.stubs(:stubbed_method).returns(:result_one)
|
162
169
|
# object.stubbed_method # => :result_one
|
163
170
|
# object.unstub(:stubbed_method)
|
164
171
|
# object.stubbed_method # => unexpected invocation: #<Mock:mock>.stubbed_method()
|
165
|
-
|
166
|
-
|
172
|
+
#
|
173
|
+
# @example Unstubbing multiple methods.
|
174
|
+
# multiplier.unstub(:double, :triple)
|
175
|
+
#
|
176
|
+
# # exactly equivalent to
|
177
|
+
#
|
178
|
+
# multiplier.unstub(:double)
|
179
|
+
# multiplier.unstub(:triple)
|
180
|
+
def unstub(*method_names)
|
181
|
+
method_names.each do |method_name|
|
182
|
+
@expectations.remove_all_matching_method(method_name)
|
183
|
+
end
|
167
184
|
end
|
168
185
|
|
169
|
-
# 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.
|
186
|
+
# Constrains the {Mock} instance so that it can only expect or stub methods to which +responder+ responds publicly. The constraint is only applied at method invocation time.
|
170
187
|
#
|
171
|
-
# A +NoMethodError+ will be raised if the +responder+ does not +#respond_to?+
|
188
|
+
# A +NoMethodError+ will be raised if the +responder+ does not publicly +#respond_to?+ the invoked method (even if the method has been expected or stubbed).
|
172
189
|
#
|
173
|
-
# The {Mock} instance will delegate its +#respond_to?+ method to the +responder+.
|
190
|
+
# The {Mock} instance will delegate its +#respond_to?+ method to the +responder+. However, the +include_all+ parameter is not passed through, so only public methods on the +responder+ will be considered.
|
174
191
|
#
|
175
192
|
# Note that the methods on +responder+ are never actually invoked.
|
176
193
|
#
|
@@ -220,11 +237,11 @@ module Mocha
|
|
220
237
|
self
|
221
238
|
end
|
222
239
|
|
223
|
-
# Constrains the {Mock} instance so that it can only expect or stub methods to which an instance of the +responder_class+ responds. The constraint is only applied at method invocation time. Note that the responder instance is instantiated using +Class#allocate+.
|
240
|
+
# Constrains the {Mock} instance so that it can only expect or stub methods to which an instance of the +responder_class+ responds publicly. The constraint is only applied at method invocation time. Note that the responder instance is instantiated using +Class#allocate+.
|
224
241
|
#
|
225
|
-
# A +NoMethodError+ will be raised if the responder instance does not +#respond_to?+
|
242
|
+
# A +NoMethodError+ will be raised if the responder instance does not publicly +#respond_to?+ the invoked method (even if the method has been expected or stubbed).
|
226
243
|
#
|
227
|
-
# The {Mock} instance will delegate its +#respond_to?+ method to the responder instance.
|
244
|
+
# The {Mock} instance will delegate its +#respond_to?+ method to the responder instance. However, the +include_all+ parameter is not passed through, so only public methods on the +responder+ will be considered.
|
228
245
|
#
|
229
246
|
# Note that the methods on the responder instance are never actually invoked.
|
230
247
|
#
|
@@ -253,7 +270,7 @@ module Mocha
|
|
253
270
|
end
|
254
271
|
|
255
272
|
# @private
|
256
|
-
def initialize(mockery, name = nil, receiver = nil
|
273
|
+
def initialize(mockery, name = nil, receiver = nil)
|
257
274
|
@mockery = mockery
|
258
275
|
@name = name || DefaultName.new(self)
|
259
276
|
@receiver = receiver || DefaultReceiver.new(self)
|
@@ -261,10 +278,7 @@ module Mocha
|
|
261
278
|
@everything_stubbed = false
|
262
279
|
@responder = nil
|
263
280
|
@unexpected_invocation = nil
|
264
|
-
|
265
|
-
Deprecation.warning('Passing a block is deprecated. Use Object#tap or define stubs/expectations with an explicit receiver instead.')
|
266
|
-
instance_eval(&block)
|
267
|
-
end
|
281
|
+
@expired = false
|
268
282
|
end
|
269
283
|
|
270
284
|
# @private
|
@@ -274,6 +288,8 @@ module Mocha
|
|
274
288
|
|
275
289
|
alias_method :__stubs__, :stubs
|
276
290
|
|
291
|
+
alias_method :__singleton_class__, :singleton_class
|
292
|
+
|
277
293
|
alias_method :quacks_like, :responds_like
|
278
294
|
alias_method :quacks_like_instance_of, :responds_like_instance_of
|
279
295
|
|
@@ -293,44 +309,31 @@ module Mocha
|
|
293
309
|
end
|
294
310
|
|
295
311
|
# @private
|
312
|
+
# rubocop:disable Style/MethodMissingSuper
|
296
313
|
def method_missing(symbol, *arguments, &block)
|
297
|
-
|
298
|
-
raise NoMethodError, "undefined method `#{symbol}' for #{self.mocha_inspect} which responds like #{@responder.mocha_inspect}"
|
299
|
-
end
|
300
|
-
if matching_expectation_allowing_invocation = all_expectations.match_allowing_invocation(symbol, *arguments)
|
301
|
-
matching_expectation_allowing_invocation.invoke(&block)
|
302
|
-
else
|
303
|
-
if (matching_expectation = all_expectations.match(symbol, *arguments)) || (!matching_expectation && !@everything_stubbed)
|
304
|
-
if @unexpected_invocation.nil?
|
305
|
-
@unexpected_invocation = UnexpectedInvocation.new(self, symbol, *arguments)
|
306
|
-
matching_expectation.invoke(&block) if matching_expectation
|
307
|
-
message = @unexpected_invocation.full_description
|
308
|
-
message << @mockery.mocha_inspect
|
309
|
-
else
|
310
|
-
message = @unexpected_invocation.short_description
|
311
|
-
end
|
312
|
-
raise ExpectationErrorFactory.build(message, caller)
|
313
|
-
end
|
314
|
-
end
|
314
|
+
handle_method_call(symbol, arguments, block)
|
315
315
|
end
|
316
|
+
ruby2_keywords(:method_missing)
|
317
|
+
# rubocop:enable Style/MethodMissingSuper
|
316
318
|
|
317
319
|
# @private
|
318
|
-
def
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
@everything_stubbed || all_expectations.matches_method?(symbol)
|
320
|
+
def handle_method_call(symbol, arguments, block)
|
321
|
+
check_expiry
|
322
|
+
check_responder_responds_to(symbol)
|
323
|
+
invocation = Invocation.new(self, symbol, arguments, block)
|
324
|
+
if (matching_expectation_allowing_invocation = all_expectations.match_allowing_invocation(invocation))
|
325
|
+
matching_expectation_allowing_invocation.invoke(invocation)
|
326
|
+
elsif (matching_expectation = all_expectations.match(invocation)) || (!matching_expectation && !@everything_stubbed)
|
327
|
+
raise_unexpected_invocation_error(invocation, matching_expectation)
|
327
328
|
end
|
328
329
|
end
|
329
330
|
|
330
331
|
# @private
|
331
|
-
|
332
|
-
|
333
|
-
|
332
|
+
def respond_to_missing?(symbol, _include_all)
|
333
|
+
if @responder
|
334
|
+
@responder.respond_to?(symbol)
|
335
|
+
else
|
336
|
+
@everything_stubbed || all_expectations.matches_method?(symbol)
|
334
337
|
end
|
335
338
|
end
|
336
339
|
|
@@ -339,6 +342,11 @@ module Mocha
|
|
339
342
|
@expectations.verified?(assertion_counter)
|
340
343
|
end
|
341
344
|
|
345
|
+
# @private
|
346
|
+
def __expire__
|
347
|
+
@expired = true
|
348
|
+
end
|
349
|
+
|
342
350
|
# @private
|
343
351
|
def mocha_inspect
|
344
352
|
@name.mocha_inspect
|
@@ -351,7 +359,7 @@ module Mocha
|
|
351
359
|
|
352
360
|
# @private
|
353
361
|
def ensure_method_not_already_defined(method_name)
|
354
|
-
|
362
|
+
__singleton_class__.send(:undef_method, method_name) if __singleton_class__.method_defined?(method_name) || __singleton_class__.private_method_defined?(method_name)
|
355
363
|
end
|
356
364
|
|
357
365
|
# @private
|
@@ -359,6 +367,34 @@ module Mocha
|
|
359
367
|
@expectations.any?
|
360
368
|
end
|
361
369
|
|
362
|
-
|
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
|
363
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
|
+
return unless @expired
|
391
|
+
|
392
|
+
sentences = [
|
393
|
+
"#{mocha_inspect} was instantiated in one test but it is receiving invocations within another test.",
|
394
|
+
'This can lead to unintended interactions between tests and hence unexpected test failures.',
|
395
|
+
'Ensure that every test correctly cleans up any state that it introduces.'
|
396
|
+
]
|
397
|
+
raise StubbingError.new(sentences.join(' '), caller)
|
398
|
+
end
|
399
|
+
end
|
364
400
|
end
|
data/lib/mocha/mockery.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'mocha/ruby_version'
|
2
1
|
require 'mocha/central'
|
3
2
|
require 'mocha/mock'
|
4
3
|
require 'mocha/names'
|
@@ -7,16 +6,42 @@ require 'mocha/state_machine'
|
|
7
6
|
require 'mocha/logger'
|
8
7
|
require 'mocha/configuration'
|
9
8
|
require 'mocha/stubbing_error'
|
9
|
+
require 'mocha/not_initialized_error'
|
10
10
|
require 'mocha/expectation_error_factory'
|
11
11
|
|
12
12
|
module Mocha
|
13
|
-
|
14
13
|
class Mockery
|
14
|
+
class Null < self
|
15
|
+
def add_mock(*)
|
16
|
+
raise_not_initialized_error
|
17
|
+
end
|
15
18
|
|
16
|
-
|
19
|
+
def add_state_machine(*)
|
20
|
+
raise_not_initialized_error
|
21
|
+
end
|
22
|
+
|
23
|
+
def stubba
|
24
|
+
Central::Null.new(&method(:raise_not_initialized_error))
|
25
|
+
end
|
17
26
|
|
27
|
+
private
|
28
|
+
|
29
|
+
def raise_not_initialized_error
|
30
|
+
message = 'Mocha methods cannot be used outside the context of a test'
|
31
|
+
raise NotInitializedError.new(message, caller)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
18
36
|
def instance
|
19
|
-
@
|
37
|
+
@instances.last || Null.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def setup
|
41
|
+
@instances ||= []
|
42
|
+
mockery = new
|
43
|
+
mockery.logger = instance.logger unless @instances.empty?
|
44
|
+
@instances.push(mockery)
|
20
45
|
end
|
21
46
|
|
22
47
|
def verify(*args)
|
@@ -25,28 +50,25 @@ module Mocha
|
|
25
50
|
|
26
51
|
def teardown
|
27
52
|
instance.teardown
|
53
|
+
ensure
|
54
|
+
@instances.pop
|
28
55
|
end
|
29
|
-
|
30
|
-
def reset_instance
|
31
|
-
@instance = nil
|
32
|
-
end
|
33
|
-
|
34
56
|
end
|
35
57
|
|
36
|
-
def named_mock(name
|
37
|
-
add_mock(Mock.new(self, Name.new(name)
|
58
|
+
def named_mock(name)
|
59
|
+
add_mock(Mock.new(self, Name.new(name)))
|
38
60
|
end
|
39
61
|
|
40
|
-
def unnamed_mock
|
41
|
-
add_mock(Mock.new(self
|
62
|
+
def unnamed_mock
|
63
|
+
add_mock(Mock.new(self))
|
42
64
|
end
|
43
65
|
|
44
|
-
def mock_impersonating(object
|
45
|
-
add_mock(Mock.new(self, ImpersonatingName.new(object), ObjectReceiver.new(object)
|
66
|
+
def mock_impersonating(object)
|
67
|
+
add_mock(Mock.new(self, ImpersonatingName.new(object), ObjectReceiver.new(object)))
|
46
68
|
end
|
47
69
|
|
48
|
-
def mock_impersonating_any_instance_of(klass
|
49
|
-
add_mock(Mock.new(self, ImpersonatingAnyInstanceName.new(klass), AnyInstanceReceiver.new(klass)
|
70
|
+
def mock_impersonating_any_instance_of(klass)
|
71
|
+
add_mock(Mock.new(self, ImpersonatingAnyInstanceName.new(klass), AnyInstanceReceiver.new(klass)))
|
50
72
|
end
|
51
73
|
|
52
74
|
def new_state_machine(name)
|
@@ -56,24 +78,22 @@ module Mocha
|
|
56
78
|
def verify(assertion_counter = nil)
|
57
79
|
unless mocks.all? { |mock| mock.__verified__?(assertion_counter) }
|
58
80
|
message = "not all expectations were satisfied\n#{mocha_inspect}"
|
59
|
-
if unsatisfied_expectations.empty?
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
81
|
+
backtrace = if unsatisfied_expectations.empty?
|
82
|
+
caller
|
83
|
+
else
|
84
|
+
unsatisfied_expectations[0].backtrace
|
85
|
+
end
|
64
86
|
raise ExpectationErrorFactory.build(message, backtrace)
|
65
87
|
end
|
66
|
-
expectations.each do |
|
67
|
-
|
68
|
-
|
69
|
-
on_stubbing_method_unnecessarily(e)
|
70
|
-
end
|
71
|
-
end
|
88
|
+
expectations.reject(&:used?).each do |expectation|
|
89
|
+
signature_proc = lambda { expectation.method_signature }
|
90
|
+
check(:stubbing_method_unnecessarily, 'method unnecessarily', signature_proc, expectation.backtrace)
|
72
91
|
end
|
73
92
|
end
|
74
93
|
|
75
94
|
def teardown
|
76
95
|
stubba.unstub_all
|
96
|
+
mocks.each(&:__expire__)
|
77
97
|
reset
|
78
98
|
end
|
79
99
|
|
@@ -90,78 +110,23 @@ module Mocha
|
|
90
110
|
end
|
91
111
|
|
92
112
|
def mocha_inspect
|
93
|
-
message =
|
94
|
-
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map
|
95
|
-
message << "satisfied expectations:\n- #{satisfied_expectations.map
|
96
|
-
message << "states:\n- #{state_machines.map
|
113
|
+
message = ''
|
114
|
+
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n" if unsatisfied_expectations.any?
|
115
|
+
message << "satisfied expectations:\n- #{satisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n" if satisfied_expectations.any?
|
116
|
+
message << "states:\n- #{state_machines.map(&:mocha_inspect).join("\n- ")}\n" if state_machines.any?
|
97
117
|
message
|
98
118
|
end
|
99
119
|
|
100
120
|
def on_stubbing(object, method)
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
on_stubbing_non_existent_method(object, method)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
unless Mocha::Configuration.allow?(:stubbing_non_public_method)
|
108
|
-
if object.method_exists?(method, include_public_methods = false)
|
109
|
-
on_stubbing_non_public_method(object, method)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
unless Mocha::Configuration.allow?(:stubbing_method_on_nil)
|
113
|
-
if object.nil?
|
114
|
-
on_stubbing_method_on_nil(object, method)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
unless Mocha::Configuration.allow?(:stubbing_method_on_non_mock_object)
|
118
|
-
on_stubbing_method_on_non_mock_object(object, method)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def on_stubbing_non_existent_method(object, method)
|
123
|
-
if Mocha::Configuration.prevent?(:stubbing_non_existent_method)
|
124
|
-
raise StubbingError.new("stubbing non-existent method: #{object.mocha_inspect}.#{method}", caller)
|
121
|
+
signature_proc = lambda { "#{object.mocha_inspect}.#{method}" }
|
122
|
+
check(:stubbing_non_existent_method, 'non-existent method', signature_proc) do
|
123
|
+
!(object.stubba_class.__method_exists__?(method, true) || object.respond_to?(method))
|
125
124
|
end
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def on_stubbing_non_public_method(object, method)
|
132
|
-
if Mocha::Configuration.prevent?(:stubbing_non_public_method)
|
133
|
-
raise StubbingError.new("stubbing non-public method: #{object.mocha_inspect}.#{method}", caller)
|
134
|
-
end
|
135
|
-
if Mocha::Configuration.warn_when?(:stubbing_non_public_method)
|
136
|
-
logger.warn "stubbing non-public method: #{object.mocha_inspect}.#{method}"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def on_stubbing_method_on_nil(object, method)
|
141
|
-
if Mocha::Configuration.prevent?(:stubbing_method_on_nil)
|
142
|
-
raise StubbingError.new("stubbing method on nil: #{object.mocha_inspect}.#{method}", caller)
|
143
|
-
end
|
144
|
-
if Mocha::Configuration.warn_when?(:stubbing_method_on_nil)
|
145
|
-
logger.warn "stubbing method on nil: #{object.mocha_inspect}.#{method}"
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def on_stubbing_method_on_non_mock_object(object, method)
|
150
|
-
if Mocha::Configuration.prevent?(:stubbing_method_on_non_mock_object)
|
151
|
-
raise StubbingError.new("stubbing method on non-mock object: #{object.mocha_inspect}.#{method}", caller)
|
152
|
-
end
|
153
|
-
if Mocha::Configuration.warn_when?(:stubbing_method_on_non_mock_object)
|
154
|
-
logger.warn "stubbing method on non-mock object: #{object.mocha_inspect}.#{method}"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def on_stubbing_method_unnecessarily(expectation)
|
159
|
-
if Mocha::Configuration.prevent?(:stubbing_method_unnecessarily)
|
160
|
-
raise StubbingError.new("stubbing method unnecessarily: #{expectation.method_signature}", expectation.backtrace)
|
161
|
-
end
|
162
|
-
if Mocha::Configuration.warn_when?(:stubbing_method_unnecessarily)
|
163
|
-
logger.warn "stubbing method unnecessarily: #{expectation.method_signature}"
|
125
|
+
check(:stubbing_non_public_method, 'non-public method', signature_proc) do
|
126
|
+
object.stubba_class.__method_exists__?(method, false)
|
164
127
|
end
|
128
|
+
check(:stubbing_method_on_nil, 'method on nil', signature_proc) { object.nil? }
|
129
|
+
check(:stubbing_method_on_non_mock_object, 'method on non-mock object', signature_proc)
|
165
130
|
end
|
166
131
|
|
167
132
|
attr_writer :logger
|
@@ -170,19 +135,27 @@ module Mocha
|
|
170
135
|
@logger ||= Logger.new($stderr)
|
171
136
|
end
|
172
137
|
|
173
|
-
|
174
138
|
private
|
175
139
|
|
140
|
+
def check(action, description, signature_proc, backtrace = caller)
|
141
|
+
treatment = Mocha.configuration.send(action)
|
142
|
+
return if (treatment == :allow) || (block_given? && !yield)
|
143
|
+
method_signature = signature_proc.call
|
144
|
+
message = "stubbing #{description}: #{method_signature}"
|
145
|
+
raise StubbingError.new(message, backtrace) if treatment == :prevent
|
146
|
+
logger.warn(message) if treatment == :warn
|
147
|
+
end
|
148
|
+
|
176
149
|
def expectations
|
177
150
|
mocks.map { |mock| mock.__expectations__.to_a }.flatten
|
178
151
|
end
|
179
152
|
|
180
153
|
def unsatisfied_expectations
|
181
|
-
expectations.reject
|
154
|
+
expectations.reject(&:verified?)
|
182
155
|
end
|
183
156
|
|
184
157
|
def satisfied_expectations
|
185
|
-
expectations.select
|
158
|
+
expectations.select(&:verified?)
|
186
159
|
end
|
187
160
|
|
188
161
|
def add_mock(mock)
|
@@ -200,7 +173,5 @@ module Mocha
|
|
200
173
|
@mocks = nil
|
201
174
|
@state_machines = nil
|
202
175
|
end
|
203
|
-
|
204
176
|
end
|
205
|
-
|
206
177
|
end
|
data/lib/mocha/names.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class ImpersonatingName
|
4
|
-
|
5
3
|
def initialize(object)
|
6
4
|
@object = object
|
7
5
|
end
|
@@ -9,11 +7,9 @@ module Mocha
|
|
9
7
|
def mocha_inspect
|
10
8
|
@object.mocha_inspect
|
11
9
|
end
|
12
|
-
|
13
10
|
end
|
14
11
|
|
15
12
|
class ImpersonatingAnyInstanceName
|
16
|
-
|
17
13
|
def initialize(klass)
|
18
14
|
@klass = klass
|
19
15
|
end
|
@@ -21,23 +17,19 @@ module Mocha
|
|
21
17
|
def mocha_inspect
|
22
18
|
"#<AnyInstance:#{@klass.mocha_inspect}>"
|
23
19
|
end
|
24
|
-
|
25
20
|
end
|
26
21
|
|
27
22
|
class Name
|
28
|
-
|
29
23
|
def initialize(name)
|
30
|
-
@name = name
|
24
|
+
@name = name.to_s
|
31
25
|
end
|
32
26
|
|
33
27
|
def mocha_inspect
|
34
28
|
"#<Mock:#{@name}>"
|
35
29
|
end
|
36
|
-
|
37
30
|
end
|
38
31
|
|
39
32
|
class DefaultName
|
40
|
-
|
41
33
|
def initialize(mock)
|
42
34
|
@mock = mock
|
43
35
|
end
|
@@ -45,9 +37,7 @@ module Mocha
|
|
45
37
|
def mocha_inspect
|
46
38
|
address = @mock.__id__ * 2
|
47
39
|
address += 0x100000000 if address < 0
|
48
|
-
"#<Mock:0x#{'
|
40
|
+
"#<Mock:0x#{format('%<address>x', address: address)}>"
|
49
41
|
end
|
50
|
-
|
51
42
|
end
|
52
|
-
|
53
43
|
end
|