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/api.rb
CHANGED
@@ -1,36 +1,62 @@
|
|
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
|
-
# @overload def mock(
|
53
|
+
# @overload def mock(name)
|
54
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
55
|
+
# @overload def mock(expected_methods_vs_return_values = {})
|
56
|
+
# @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.
|
57
|
+
# @overload def mock(name, expected_methods_vs_return_values = {})
|
58
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
59
|
+
# @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
60
|
#
|
35
61
|
# @example Using expected_methods_vs_return_values Hash to setup expectations.
|
36
62
|
# def test_motor_starts_and_stops
|
@@ -39,34 +65,26 @@ module Mocha
|
|
39
65
|
# assert motor.stop
|
40
66
|
# # an error will be raised unless both Motor#start and Motor#stop have been called
|
41
67
|
# end
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
# expects(:start).with(100.rpm).returns(true)
|
46
|
-
# stubs(:stop).returns(true)
|
47
|
-
# end
|
48
|
-
# assert motor.start(100.rpm)
|
49
|
-
# assert motor.stop
|
50
|
-
# # an error will only be raised if Motor#start(100.rpm) has not been called
|
51
|
-
# end
|
52
|
-
def mock(*arguments, &block)
|
53
|
-
name = arguments.shift if arguments.first.is_a?(String)
|
68
|
+
#
|
69
|
+
def mock(*arguments)
|
70
|
+
name = arguments.shift.to_s if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
54
71
|
expectations = arguments.shift || {}
|
55
|
-
mock = name ? Mockery.instance.named_mock(name
|
72
|
+
mock = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
56
73
|
mock.expects(expectations)
|
57
74
|
mock
|
58
75
|
end
|
59
76
|
|
60
77
|
# Builds a new mock object
|
61
78
|
#
|
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
79
|
# @return [Mock] a new mock object
|
66
80
|
#
|
67
|
-
# @overload def stub(name
|
68
|
-
#
|
69
|
-
# @overload def stub(
|
81
|
+
# @overload def stub(name)
|
82
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
83
|
+
# @overload def stub(stubbed_methods_vs_return_values = {})
|
84
|
+
# @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.
|
85
|
+
# @overload def stub(name, stubbed_methods_vs_return_values = {})
|
86
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
87
|
+
# @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.
|
70
88
|
#
|
71
89
|
# @example Using stubbed_methods_vs_return_values Hash to setup stubbed methods.
|
72
90
|
# def test_motor_starts_and_stops
|
@@ -75,35 +93,25 @@ module Mocha
|
|
75
93
|
# assert motor.stop
|
76
94
|
# # an error will not be raised even if either Motor#start or Motor#stop has not been called
|
77
95
|
# end
|
78
|
-
|
79
|
-
|
80
|
-
# def test_motor_starts_and_stops
|
81
|
-
# motor = stub('motor') do
|
82
|
-
# expects(:start).with(100.rpm).returns(true)
|
83
|
-
# stubs(:stop).returns(true)
|
84
|
-
# end
|
85
|
-
# assert motor.start(100.rpm)
|
86
|
-
# assert motor.stop
|
87
|
-
# # an error will only be raised if Motor#start(100.rpm) has not been called
|
88
|
-
# end
|
89
|
-
def stub(*arguments, &block)
|
90
|
-
name = arguments.shift if arguments.first.is_a?(String)
|
96
|
+
def stub(*arguments)
|
97
|
+
name = arguments.shift.to_s if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
91
98
|
expectations = arguments.shift || {}
|
92
|
-
stub = name ? Mockery.instance.named_mock(name
|
99
|
+
stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
93
100
|
stub.stubs(expectations)
|
94
101
|
stub
|
95
102
|
end
|
96
103
|
|
97
104
|
# Builds a mock object that accepts calls to any method. By default it will return +nil+ for any method call.
|
98
105
|
#
|
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
106
|
# @return [Mock] a new mock object
|
103
107
|
#
|
104
|
-
# @overload def stub_everything(name
|
105
|
-
#
|
106
|
-
# @overload def stub_everything(
|
108
|
+
# @overload def stub_everything(name)
|
109
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
110
|
+
# @overload def stub_everything(stubbed_methods_vs_return_values = {})
|
111
|
+
# @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.
|
112
|
+
# @overload def stub_everything(name, stubbed_methods_vs_return_values = {})
|
113
|
+
# @param [String, Symbol] name identifies mock object in error messages.
|
114
|
+
# @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
115
|
#
|
108
116
|
# @example Ignore invocations of irrelevant methods.
|
109
117
|
# def test_motor_stops
|
@@ -112,10 +120,10 @@ module Mocha
|
|
112
120
|
# assert_nil motor.irrelevant_method_2 # => no error raised
|
113
121
|
# assert motor.stop
|
114
122
|
# end
|
115
|
-
def stub_everything(*arguments
|
116
|
-
name = arguments.shift if arguments.first.is_a?(String)
|
123
|
+
def stub_everything(*arguments)
|
124
|
+
name = arguments.shift if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
117
125
|
expectations = arguments.shift || {}
|
118
|
-
stub = name ? Mockery.instance.named_mock(name
|
126
|
+
stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
119
127
|
stub.stub_everything
|
120
128
|
stub.stubs(expectations)
|
121
129
|
stub
|
@@ -132,11 +140,22 @@ module Mocha
|
|
132
140
|
# @example Ensure methods on egg are invoked in correct order.
|
133
141
|
# breakfast = sequence('breakfast')
|
134
142
|
#
|
135
|
-
# egg = mock('egg')
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
143
|
+
# egg = mock('egg')
|
144
|
+
# egg.expects(:crack).in_sequence(breakfast)
|
145
|
+
# egg.expects(:fry).in_sequence(breakfast)
|
146
|
+
# egg.expects(:eat).in_sequence(breakfast)
|
147
|
+
#
|
148
|
+
# @example Ensure methods across multiple objects are invoked in correct order.
|
149
|
+
# sequence = sequence(:task_order)
|
150
|
+
#
|
151
|
+
# task_one = mock("task_one")
|
152
|
+
# task_two = mock("task_two")
|
153
|
+
#
|
154
|
+
# task_one.expects(:execute).in_sequence(sequence)
|
155
|
+
# task_two.expects(:execute).in_sequence(sequence)
|
156
|
+
#
|
157
|
+
# task_one.execute
|
158
|
+
# task_two.execute
|
140
159
|
def sequence(name)
|
141
160
|
Sequence.new(name)
|
142
161
|
end
|
@@ -159,18 +178,15 @@ module Mocha
|
|
159
178
|
# @example Constrain expected invocations to occur in particular states.
|
160
179
|
# power = states('power').starts_as('off')
|
161
180
|
#
|
162
|
-
# radio = mock('radio')
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
# end
|
181
|
+
# radio = mock('radio')
|
182
|
+
# radio.expects(:switch_on).then(power.is('on'))
|
183
|
+
# radio.expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
|
184
|
+
# radio.expects(:adjust_volume).with(+5).when(power.is('on'))
|
185
|
+
# radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
|
186
|
+
# radio.expects(:adjust_volume).with(-5).when(power.is('on'))
|
187
|
+
# radio.expects(:switch_off).then(power.is('off'))
|
170
188
|
def states(name)
|
171
189
|
Mockery.instance.new_state_machine(name)
|
172
190
|
end
|
173
|
-
|
174
191
|
end
|
175
|
-
|
176
192
|
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
|