mocha 1.2.1 → 1.16.1
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 +61 -0
- data/.rubocop_todo.yml +27 -0
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +4 -9
- data/Gemfile +29 -0
- data/README.md +104 -106
- data/RELEASE.md +277 -1
- data/Rakefile +46 -44
- data/gemfiles/Gemfile.minitest.latest +1 -0
- data/gemfiles/Gemfile.test-unit.latest +2 -5
- data/init.rb +1 -3
- data/lib/mocha/any_instance_method.rb +9 -62
- data/lib/mocha/api.rb +144 -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 +372 -18
- 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 +125 -89
- 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/nothing.rb +4 -4
- data/lib/mocha/integration/mini_test/version_13.rb +4 -1
- data/lib/mocha/integration/mini_test/version_140.rb +4 -1
- data/lib/mocha/integration/mini_test/version_141.rb +4 -1
- data/lib/mocha/integration/mini_test/version_142_to_172.rb +4 -1
- data/lib/mocha/integration/mini_test/version_200.rb +4 -1
- data/lib/mocha/integration/mini_test/version_201_to_222.rb +4 -1
- data/lib/mocha/integration/mini_test/version_2110_to_2111.rb +4 -1
- data/lib/mocha/integration/mini_test/version_2112_to_320.rb +4 -1
- data/lib/mocha/integration/mini_test/version_230_to_2101.rb +4 -1
- data/lib/mocha/integration/mini_test.rb +7 -0
- 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/gem_version_200.rb +5 -2
- data/lib/mocha/integration/test_unit/gem_version_201_to_202.rb +5 -2
- data/lib/mocha/integration/test_unit/gem_version_203_to_220.rb +5 -2
- data/lib/mocha/integration/test_unit/gem_version_230_to_250.rb +5 -2
- data/lib/mocha/integration/test_unit/nothing.rb +4 -4
- data/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb +4 -1
- data/lib/mocha/integration/test_unit.rb +7 -2
- data/lib/mocha/integration.rb +2 -5
- data/lib/mocha/invocation.rb +86 -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 +9 -0
- data/lib/mocha/mock.rb +102 -58
- 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 +6 -12
- data/lib/mocha/parameter_matchers/equals.rb +0 -6
- data/lib/mocha/parameter_matchers/{query_string.rb → equivalent_uri.rb} +15 -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 +18 -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/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 +6 -9
- 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 +8 -1
- data/lib/mocha/sequence.rb +4 -9
- data/lib/mocha/setup.rb +5 -0
- data/lib/mocha/single_return_value.rb +2 -5
- data/lib/mocha/state_machine.rb +33 -46
- data/lib/mocha/stubbed_method.rb +124 -0
- data/lib/mocha/stubbing_error.rb +2 -13
- data/lib/mocha/test_unit.rb +8 -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 +25 -247
- 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/lib/mocha/class_method.rb +0 -119
- data/lib/mocha/integration/test_unit/ruby_version_185_and_below.rb +0 -58
- 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/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/api.rb
CHANGED
@@ -1,36 +1,63 @@
|
|
1
|
+
require 'mocha/ruby_version'
|
1
2
|
require 'mocha/parameter_matchers'
|
2
3
|
require 'mocha/hooks'
|
3
4
|
require 'mocha/mockery'
|
4
5
|
require 'mocha/sequence'
|
5
6
|
require 'mocha/object_methods'
|
6
|
-
require 'mocha/module_methods'
|
7
7
|
require 'mocha/class_methods'
|
8
8
|
|
9
9
|
module Mocha
|
10
|
-
|
11
10
|
# Methods added to +Test::Unit::TestCase+, +MiniTest::Unit::TestCase+ or equivalent.
|
11
|
+
# The mock creation methods are {#mock}, {#stub} and {#stub_everything}, all of which return a #{Mock}
|
12
|
+
# which can be further modified by {Mock#responds_like} and {Mock#responds_like_instance_of} methods,
|
13
|
+
# both of which return a {Mock}, too, and can therefore, be chained to the original creation methods.
|
14
|
+
#
|
15
|
+
# {Mock#responds_like} and {Mock#responds_like_instance_of} force the mock to indicate what it is
|
16
|
+
# supposed to be mocking, thus making it a safer verifying mock. They check that the underlying +responder+
|
17
|
+
# will actually respond to the methods being stubbed, throwing a +NoMethodError+ upon invocation otherwise.
|
18
|
+
#
|
19
|
+
# @example Verifying mock using {Mock#responds_like_instance_of}
|
20
|
+
# class Sheep
|
21
|
+
# def initialize
|
22
|
+
# raise "some awkward code we don't want to call"
|
23
|
+
# end
|
24
|
+
# def chew(grass); end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# sheep = mock('sheep').responds_like_instance_of(Sheep)
|
28
|
+
# sheep.expects(:chew)
|
29
|
+
# sheep.expects(:foo)
|
30
|
+
# sheep.respond_to?(:chew) # => true
|
31
|
+
# sheep.respond_to?(:foo) # => false
|
32
|
+
# sheep.chew
|
33
|
+
# sheep.foo # => raises NoMethodError exception
|
12
34
|
module API
|
13
|
-
|
14
35
|
include ParameterMatchers
|
15
36
|
include Hooks
|
16
37
|
|
17
38
|
# @private
|
18
|
-
def self.included(
|
39
|
+
def self.included(_mod)
|
19
40
|
Object.send(:include, Mocha::ObjectMethods)
|
20
|
-
Module.send(:include, Mocha::ModuleMethods)
|
21
41
|
Class.send(:include, Mocha::ClassMethods)
|
22
42
|
end
|
23
43
|
|
44
|
+
# @private
|
45
|
+
def self.extended(mod)
|
46
|
+
included(mod)
|
47
|
+
end
|
48
|
+
|
24
49
|
# Builds a new mock object
|
25
50
|
#
|
26
|
-
# @param [String] name identifies mock object in error messages.
|
27
|
-
# @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 {Mock#expects} were called multiple times.
|
28
|
-
# @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup expectations.
|
29
51
|
# @return [Mock] a new mock object
|
30
52
|
#
|
31
|
-
# @overload def mock(name
|
32
|
-
#
|
33
|
-
#
|
53
|
+
# @overload def mock(name)
|
54
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
55
|
+
# @note Prior to v1.10.0 when +name+ was a +Symbol+, this method returned an unnamed +Mock+ that expected the method identified by +name+. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using {Configuration#reinstate_undocumented_behaviour_from_v1_9=}.
|
56
|
+
# @overload def mock(expected_methods_vs_return_values = {})
|
57
|
+
# @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 {Mock#expects} were called multiple times.
|
58
|
+
# @overload def mock(name, expected_methods_vs_return_values = {})
|
59
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
60
|
+
# @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 {Mock#expects} were called multiple times.
|
34
61
|
#
|
35
62
|
# @example Using expected_methods_vs_return_values Hash to setup expectations.
|
36
63
|
# def test_motor_starts_and_stops
|
@@ -39,34 +66,44 @@ module Mocha
|
|
39
66
|
# assert motor.stop
|
40
67
|
# # an error will be raised unless both Motor#start and Motor#stop have been called
|
41
68
|
# end
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
69
|
+
#
|
70
|
+
def mock(*arguments) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
71
|
+
if Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
|
72
|
+
if arguments.first.is_a?(Symbol)
|
73
|
+
method_name = arguments[0]
|
74
|
+
Deprecation.warning(
|
75
|
+
"Explicitly include `#{method_name}` in Hash of expected methods vs return values,",
|
76
|
+
" e.g. `mock(:#{method_name} => nil)`."
|
77
|
+
)
|
78
|
+
if arguments[1]
|
79
|
+
Deprecation.warning(
|
80
|
+
"In this case the 2nd argument for `mock(:##{method_name}, ...)` is ignored,",
|
81
|
+
' but in the future a Hash of expected methods vs return values will be respected.'
|
82
|
+
)
|
83
|
+
end
|
84
|
+
elsif arguments.first.is_a?(String)
|
85
|
+
name = arguments.shift
|
86
|
+
end
|
87
|
+
elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
88
|
+
name = arguments.shift
|
89
|
+
end
|
54
90
|
expectations = arguments.shift || {}
|
55
|
-
mock = name ? Mockery.instance.named_mock(name
|
91
|
+
mock = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
56
92
|
mock.expects(expectations)
|
57
93
|
mock
|
58
94
|
end
|
59
95
|
|
60
96
|
# Builds a new mock object
|
61
97
|
#
|
62
|
-
# @param [String] name identifies mock object in error messages.
|
63
|
-
# @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 {Mock#stubs} were called multiple times.
|
64
|
-
# @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup stubbed methods.
|
65
98
|
# @return [Mock] a new mock object
|
66
99
|
#
|
67
|
-
# @overload def stub(name
|
68
|
-
#
|
69
|
-
#
|
100
|
+
# @overload def stub(name)
|
101
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
102
|
+
# @note Prior to v1.10.0 when +name+ was a +Symbol+, this method returned an unnamed +Mock+ that stubbed the method identified by +name+. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using {Configuration#reinstate_undocumented_behaviour_from_v1_9=}.
|
103
|
+
# @overload def stub(stubbed_methods_vs_return_values = {})
|
104
|
+
# @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 {Mock#stubs} were called multiple times.
|
105
|
+
# @overload def stub(name, stubbed_methods_vs_return_values = {})
|
106
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
70
107
|
#
|
71
108
|
# @example Using stubbed_methods_vs_return_values Hash to setup stubbed methods.
|
72
109
|
# def test_motor_starts_and_stops
|
@@ -75,35 +112,46 @@ module Mocha
|
|
75
112
|
# assert motor.stop
|
76
113
|
# # an error will not be raised even if either Motor#start or Motor#stop has not been called
|
77
114
|
# end
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
115
|
+
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
116
|
+
def stub(*arguments)
|
117
|
+
if Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
|
118
|
+
if arguments.first.is_a?(Symbol)
|
119
|
+
method_name = arguments[0]
|
120
|
+
Deprecation.warning(
|
121
|
+
"Explicitly include `#{method_name}` in Hash of stubbed methods vs return values,",
|
122
|
+
" e.g. `stub(:#{method_name} => nil)`."
|
123
|
+
)
|
124
|
+
if arguments[1]
|
125
|
+
Deprecation.warning(
|
126
|
+
"In this case the 2nd argument for `stub(:##{method_name}, ...)` is ignored,",
|
127
|
+
' but in the future a Hash of stubbed methods vs return values will be respected.'
|
128
|
+
)
|
129
|
+
end
|
130
|
+
elsif arguments.first.is_a?(String)
|
131
|
+
name = arguments.shift
|
132
|
+
end
|
133
|
+
elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
134
|
+
name = arguments.shift
|
135
|
+
end
|
91
136
|
expectations = arguments.shift || {}
|
92
|
-
stub = name ? Mockery.instance.named_mock(name
|
137
|
+
stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
93
138
|
stub.stubs(expectations)
|
94
139
|
stub
|
95
140
|
end
|
141
|
+
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
96
142
|
|
97
143
|
# Builds a mock object that accepts calls to any method. By default it will return +nil+ for any method call.
|
98
144
|
#
|
99
|
-
# @param [String] name identifies mock object in error messages.
|
100
|
-
# @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 {Mock#stubs} were called multiple times.
|
101
|
-
# @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup stubbed methods.
|
102
145
|
# @return [Mock] a new mock object
|
103
146
|
#
|
104
|
-
# @overload def stub_everything(name
|
105
|
-
#
|
106
|
-
#
|
147
|
+
# @overload def stub_everything(name)
|
148
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
149
|
+
# @note Prior to v1.10.0 when +name+ was a +Symbol+, this method returned an unnamed +Mock+ that stubbed the method identified by +name+. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using {Configuration#reinstate_undocumented_behaviour_from_v1_9=}.
|
150
|
+
# @overload def stub_everything(stubbed_methods_vs_return_values = {})
|
151
|
+
# @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 {Mock#stubs} were called multiple times.
|
152
|
+
# @overload def stub_everything(name, stubbed_methods_vs_return_values = {})
|
153
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
154
|
+
# @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 {Mock#stubs} were called multiple times.
|
107
155
|
#
|
108
156
|
# @example Ignore invocations of irrelevant methods.
|
109
157
|
# def test_motor_stops
|
@@ -112,14 +160,34 @@ module Mocha
|
|
112
160
|
# assert_nil motor.irrelevant_method_2 # => no error raised
|
113
161
|
# assert motor.stop
|
114
162
|
# end
|
115
|
-
|
116
|
-
|
163
|
+
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
164
|
+
def stub_everything(*arguments)
|
165
|
+
if Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
|
166
|
+
if arguments.first.is_a?(Symbol)
|
167
|
+
method_name = arguments[0]
|
168
|
+
Deprecation.warning(
|
169
|
+
"Explicitly include `#{method_name}` in Hash of stubbed methods vs return values,",
|
170
|
+
" e.g. `stub_everything(:#{method_name} => nil)`."
|
171
|
+
)
|
172
|
+
if arguments[1]
|
173
|
+
Deprecation.warning(
|
174
|
+
"In this case the 2nd argument for `stub_everything(:##{method_name}, ...)` is ignored,",
|
175
|
+
' but in the future a Hash of stubbed methods vs return values will be respected.'
|
176
|
+
)
|
177
|
+
end
|
178
|
+
elsif arguments.first.is_a?(String)
|
179
|
+
name = arguments.shift
|
180
|
+
end
|
181
|
+
elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
182
|
+
name = arguments.shift
|
183
|
+
end
|
117
184
|
expectations = arguments.shift || {}
|
118
|
-
stub = name ? Mockery.instance.named_mock(name
|
185
|
+
stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
119
186
|
stub.stub_everything
|
120
187
|
stub.stubs(expectations)
|
121
188
|
stub
|
122
189
|
end
|
190
|
+
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
123
191
|
|
124
192
|
# Builds a new sequence which can be used to constrain the order in which expectations can occur.
|
125
193
|
#
|
@@ -132,11 +200,22 @@ module Mocha
|
|
132
200
|
# @example Ensure methods on egg are invoked in correct order.
|
133
201
|
# breakfast = sequence('breakfast')
|
134
202
|
#
|
135
|
-
# egg = mock('egg')
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
203
|
+
# egg = mock('egg')
|
204
|
+
# egg.expects(:crack).in_sequence(breakfast)
|
205
|
+
# egg.expects(:fry).in_sequence(breakfast)
|
206
|
+
# egg.expects(:eat).in_sequence(breakfast)
|
207
|
+
#
|
208
|
+
# @example Ensure methods across multiple objects are invoked in correct order.
|
209
|
+
# sequence = sequence(:task_order)
|
210
|
+
#
|
211
|
+
# task_one = mock("task_one")
|
212
|
+
# task_two = mock("task_two")
|
213
|
+
#
|
214
|
+
# task_one.expects(:execute).in_sequence(sequence)
|
215
|
+
# task_two.expects(:execute).in_sequence(sequence)
|
216
|
+
#
|
217
|
+
# task_one.execute
|
218
|
+
# task_two.execute
|
140
219
|
def sequence(name)
|
141
220
|
Sequence.new(name)
|
142
221
|
end
|
@@ -159,18 +238,15 @@ module Mocha
|
|
159
238
|
# @example Constrain expected invocations to occur in particular states.
|
160
239
|
# power = states('power').starts_as('off')
|
161
240
|
#
|
162
|
-
# radio = mock('radio')
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
# end
|
241
|
+
# radio = mock('radio')
|
242
|
+
# radio.expects(:switch_on).then(power.is('on'))
|
243
|
+
# radio.expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
|
244
|
+
# radio.expects(:adjust_volume).with(+5).when(power.is('on'))
|
245
|
+
# radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
|
246
|
+
# radio.expects(:adjust_volume).with(-5).when(power.is('on'))
|
247
|
+
# radio.expects(:switch_off).then(power.is('off'))
|
170
248
|
def states(name)
|
171
249
|
Mockery.instance.new_state_machine(name)
|
172
250
|
end
|
173
|
-
|
174
251
|
end
|
175
|
-
|
176
252
|
end
|
@@ -1,21 +1,17 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class ArgumentIterator
|
4
|
-
|
5
3
|
def initialize(argument)
|
6
4
|
@argument = argument
|
7
5
|
end
|
8
6
|
|
9
|
-
def each
|
10
|
-
if @argument.is_a?(Hash)
|
7
|
+
def each
|
8
|
+
if @argument.is_a?(Hash)
|
11
9
|
@argument.each do |method_name, return_value|
|
12
|
-
|
10
|
+
yield method_name, return_value
|
13
11
|
end
|
14
12
|
else
|
15
|
-
|
13
|
+
yield @argument
|
16
14
|
end
|
17
15
|
end
|
18
|
-
|
19
16
|
end
|
20
|
-
|
21
17
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class BacktraceFilter
|
4
|
-
|
5
|
-
LIB_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), "..")) + File::SEPARATOR
|
3
|
+
LIB_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), '..')) + File::SEPARATOR
|
6
4
|
|
7
5
|
def initialize(lib_directory = LIB_DIRECTORY)
|
8
6
|
@path_pattern = Regexp.new(lib_directory)
|
@@ -11,7 +9,5 @@ module Mocha
|
|
11
9
|
def filtered(backtrace)
|
12
10
|
backtrace.reject { |location| @path_pattern.match(File.expand_path(location)) }
|
13
11
|
end
|
14
|
-
|
15
12
|
end
|
16
|
-
|
17
13
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Mocha
|
2
|
+
module BlockMatchers
|
3
|
+
class OptionalBlock
|
4
|
+
def match?(_actual_block)
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
def mocha_inspect; end
|
9
|
+
end
|
10
|
+
|
11
|
+
class BlockGiven
|
12
|
+
def match?(actual_block)
|
13
|
+
!actual_block.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def mocha_inspect
|
17
|
+
'with block given'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class NoBlockGiven
|
22
|
+
def match?(actual_block)
|
23
|
+
actual_block.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def mocha_inspect
|
27
|
+
'with no block given'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/mocha/cardinality.rb
CHANGED
@@ -1,95 +1,106 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class Cardinality
|
4
|
-
|
5
3
|
INFINITY = 1 / 0.0
|
6
4
|
|
7
|
-
|
5
|
+
def initialize(required = 0, maximum = INFINITY)
|
6
|
+
update(required, maximum)
|
7
|
+
@invocations = []
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def exactly(count)
|
11
|
+
update(count, count)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def at_least(count)
|
15
|
+
update(count, INFINITY)
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def at_most(count)
|
19
|
+
update(0, count)
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
22
|
+
def times(range_or_count)
|
23
|
+
case range_or_count
|
24
|
+
when Range then update(range_or_count.first, range_or_count.last)
|
25
|
+
else update(range_or_count, range_or_count)
|
26
26
|
end
|
27
|
-
|
28
27
|
end
|
29
28
|
|
30
|
-
def
|
31
|
-
@
|
29
|
+
def <<(invocation)
|
30
|
+
@invocations << invocation
|
32
31
|
end
|
33
32
|
|
34
|
-
def invocations_allowed?
|
35
|
-
|
33
|
+
def invocations_allowed?
|
34
|
+
@invocations.size < maximum
|
36
35
|
end
|
37
36
|
|
38
|
-
def satisfied?
|
39
|
-
|
37
|
+
def satisfied?
|
38
|
+
@invocations.size >= required
|
40
39
|
end
|
41
40
|
|
42
41
|
def needs_verifying?
|
43
42
|
!allowed_any_number_of_times?
|
44
43
|
end
|
45
44
|
|
46
|
-
def verified?
|
47
|
-
(
|
45
|
+
def verified?
|
46
|
+
(@invocations.size >= required) && (@invocations.size <= maximum)
|
48
47
|
end
|
49
48
|
|
50
49
|
def allowed_any_number_of_times?
|
51
|
-
required
|
50
|
+
required.zero? && infinite?(maximum)
|
52
51
|
end
|
53
52
|
|
54
|
-
def used?
|
55
|
-
|
53
|
+
def used?
|
54
|
+
@invocations.any? || maximum.zero?
|
56
55
|
end
|
57
56
|
|
58
|
-
|
57
|
+
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
58
|
+
def anticipated_times
|
59
59
|
if allowed_any_number_of_times?
|
60
|
-
|
60
|
+
'allowed any number of times'
|
61
|
+
elsif required.zero? && maximum.zero?
|
62
|
+
"expected #{count(maximum)}"
|
63
|
+
elsif required == maximum
|
64
|
+
"expected exactly #{count(required)}"
|
65
|
+
elsif infinite?(maximum)
|
66
|
+
"expected at least #{count(required)}"
|
67
|
+
elsif required.zero?
|
68
|
+
"expected at most #{count(maximum)}"
|
61
69
|
else
|
62
|
-
|
63
|
-
"expected never"
|
64
|
-
elsif required == maximum
|
65
|
-
"expected exactly #{times(required)}"
|
66
|
-
elsif infinite?(maximum)
|
67
|
-
"expected at least #{times(required)}"
|
68
|
-
elsif required == 0
|
69
|
-
"expected at most #{times(maximum)}"
|
70
|
-
else
|
71
|
-
"expected between #{required} and #{times(maximum)}"
|
72
|
-
end
|
70
|
+
"expected between #{required} and #{count(maximum)}"
|
73
71
|
end
|
74
72
|
end
|
73
|
+
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
74
|
+
|
75
|
+
def invoked_times
|
76
|
+
"invoked #{count(@invocations.size)}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def actual_invocations
|
80
|
+
@invocations.map(&:full_description).join
|
81
|
+
end
|
75
82
|
|
76
83
|
protected
|
77
84
|
|
78
85
|
attr_reader :required, :maximum
|
79
86
|
|
80
|
-
def
|
87
|
+
def count(number)
|
81
88
|
case number
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
when 0 then 'never'
|
90
|
+
when 1 then 'once'
|
91
|
+
when 2 then 'twice'
|
92
|
+
else "#{number} times"
|
86
93
|
end
|
87
94
|
end
|
88
95
|
|
96
|
+
def update(required, maximum)
|
97
|
+
@required = required
|
98
|
+
@maximum = maximum
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
89
102
|
def infinite?(number)
|
90
103
|
number.respond_to?(:infinite?) && number.infinite?
|
91
104
|
end
|
92
|
-
|
93
105
|
end
|
94
|
-
|
95
106
|
end
|
data/lib/mocha/central.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class Central
|
3
|
+
class Null < self
|
4
|
+
def initialize(&block)
|
5
|
+
super
|
6
|
+
@raise_not_initialized_error = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def stub(*)
|
10
|
+
@raise_not_initialized_error.call
|
11
|
+
end
|
12
|
+
|
13
|
+
def unstub(*)
|
14
|
+
@raise_not_initialized_error.call
|
15
|
+
end
|
16
|
+
end
|
4
17
|
|
5
18
|
attr_accessor :stubba_methods
|
6
19
|
|
@@ -9,25 +22,21 @@ module Mocha
|
|
9
22
|
end
|
10
23
|
|
11
24
|
def stub(method)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
25
|
+
return if stubba_methods.detect { |m| m.matches?(method) }
|
26
|
+
method.stub
|
27
|
+
stubba_methods.push(method)
|
16
28
|
end
|
17
29
|
|
18
30
|
def unstub(method)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
31
|
+
return unless (existing = stubba_methods.detect { |m| m.matches?(method) })
|
32
|
+
existing.unstub
|
33
|
+
stubba_methods.delete(existing)
|
23
34
|
end
|
24
35
|
|
25
36
|
def unstub_all
|
26
|
-
while stubba_methods.any?
|
37
|
+
while stubba_methods.any?
|
27
38
|
unstub(stubba_methods.first)
|
28
39
|
end
|
29
40
|
end
|
30
|
-
|
31
41
|
end
|
32
|
-
|
33
42
|
end
|
data/lib/mocha/class_methods.rb
CHANGED
@@ -1,46 +1,36 @@
|
|
1
1
|
require 'mocha/mockery'
|
2
|
-
require 'mocha/class_method'
|
3
2
|
require 'mocha/any_instance_method'
|
4
3
|
|
5
4
|
module Mocha
|
6
|
-
|
7
5
|
# Methods added to all classes to allow mocking and stubbing on real (i.e. non-mock) objects.
|
8
6
|
module ClassMethods
|
9
|
-
|
10
|
-
# @private
|
11
|
-
def stubba_method
|
12
|
-
Mocha::ClassMethod
|
13
|
-
end
|
14
|
-
|
15
7
|
# @private
|
16
8
|
class AnyInstance
|
17
|
-
|
18
9
|
def initialize(klass)
|
19
10
|
@stubba_object = klass
|
20
11
|
end
|
21
12
|
|
22
|
-
def mocha
|
23
|
-
|
13
|
+
def mocha(instantiate = true)
|
14
|
+
if instantiate
|
15
|
+
@mocha ||= Mocha::Mockery.instance.mock_impersonating_any_instance_of(@stubba_object)
|
16
|
+
else
|
17
|
+
defined?(@mocha) ? @mocha : nil
|
18
|
+
end
|
24
19
|
end
|
25
20
|
|
26
21
|
def stubba_method
|
27
22
|
Mocha::AnyInstanceMethod
|
28
23
|
end
|
29
24
|
|
30
|
-
def
|
25
|
+
def stubba_class
|
31
26
|
@stubba_object
|
32
27
|
end
|
33
28
|
|
34
|
-
def
|
35
|
-
|
36
|
-
return true if @stubba_object.public_instance_methods(include_superclass_methods = true).include?(method)
|
37
|
-
return true if @stubba_object.allocate.respond_to?(method.to_sym)
|
38
|
-
end
|
39
|
-
return true if @stubba_object.protected_instance_methods(include_superclass_methods = true).include?(method)
|
40
|
-
return true if @stubba_object.private_instance_methods(include_superclass_methods = true).include?(method)
|
41
|
-
return false
|
29
|
+
def respond_to?(symbol, include_all = false)
|
30
|
+
@stubba_object.allocate.respond_to?(symbol.to_sym, include_all)
|
42
31
|
end
|
43
32
|
|
33
|
+
attr_reader :stubba_object
|
44
34
|
end
|
45
35
|
|
46
36
|
# @return [Mock] a mock object which will detect calls to any instance of this class.
|
@@ -59,6 +49,14 @@ module Mocha
|
|
59
49
|
@any_instance ||= AnyInstance.new(self)
|
60
50
|
end
|
61
51
|
|
52
|
+
# @private
|
53
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
54
|
+
def __method_visibility__(method, include_public_methods = true)
|
55
|
+
(include_public_methods && public_method_defined?(method) && :public) ||
|
56
|
+
(protected_method_defined?(method) && :protected) ||
|
57
|
+
(private_method_defined?(method) && :private)
|
58
|
+
end
|
59
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
60
|
+
alias_method :__method_exists__?, :__method_visibility__
|
62
61
|
end
|
63
|
-
|
64
62
|
end
|