mocha 0.10.5 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/FUNDING.yml +1 -0
- data/.rubocop.yml +61 -0
- data/.rubocop_todo.yml +27 -0
- data/.yardopts +24 -0
- data/CONTRIBUTING.md +7 -0
- data/COPYING.md +3 -0
- data/Gemfile +2 -2
- data/{MIT-LICENSE.rdoc → MIT-LICENSE.md} +1 -1
- data/README.md +363 -0
- data/{RELEASE.rdoc → RELEASE.md} +436 -35
- data/Rakefile +87 -87
- data/gemfiles/Gemfile.minitest.latest +2 -2
- data/gemfiles/Gemfile.test-unit.latest +6 -2
- data/init.rb +1 -3
- data/lib/mocha/any_instance_method.rb +12 -45
- data/lib/mocha/api.rb +199 -131
- data/lib/mocha/argument_iterator.rb +6 -10
- data/lib/mocha/backtrace_filter.rb +1 -5
- data/lib/mocha/block_matcher.rb +31 -0
- data/lib/mocha/cardinality.rb +77 -66
- data/lib/mocha/central.rb +27 -18
- data/lib/mocha/change_state_side_effect.rb +3 -7
- data/lib/mocha/class_methods.rb +62 -0
- data/lib/mocha/configuration.rb +399 -46
- data/lib/mocha/debug.rb +12 -0
- data/lib/mocha/deprecation.rb +11 -12
- data/lib/mocha/detection/mini_test.rb +23 -0
- data/lib/mocha/detection/test_unit.rb +27 -0
- data/lib/mocha/error_with_filtered_backtrace.rb +13 -0
- data/lib/mocha/exception_raiser.rb +8 -10
- data/lib/mocha/expectation.rb +290 -151
- data/lib/mocha/expectation_error.rb +6 -13
- data/lib/mocha/expectation_error_factory.rb +35 -0
- data/lib/mocha/expectation_list.rb +22 -22
- data/lib/mocha/hooks.rb +42 -0
- data/lib/mocha/in_state_ordering_constraint.rb +3 -7
- data/lib/mocha/inspect.rb +35 -43
- data/lib/mocha/instance_method.rb +12 -21
- data/lib/mocha/integration/assertion_counter.rb +13 -0
- data/lib/mocha/integration/mini_test/adapter.rb +52 -0
- data/lib/mocha/integration/mini_test/exception_translation.rb +1 -7
- data/lib/mocha/integration/mini_test/nothing.rb +19 -0
- data/lib/mocha/integration/mini_test/version_13.rb +35 -25
- data/lib/mocha/integration/mini_test/version_140.rb +35 -26
- data/lib/mocha/integration/mini_test/version_141.rb +43 -34
- data/lib/mocha/integration/mini_test/version_142_to_172.rb +44 -35
- data/lib/mocha/integration/mini_test/version_200.rb +45 -36
- data/lib/mocha/integration/mini_test/version_201_to_222.rb +44 -35
- data/lib/mocha/integration/mini_test/version_2110_to_2111.rb +70 -0
- data/lib/mocha/integration/mini_test/version_2112_to_320.rb +73 -0
- data/lib/mocha/integration/mini_test/version_230_to_2101.rb +68 -0
- data/lib/mocha/integration/mini_test.rb +51 -49
- data/lib/mocha/integration/monkey_patcher.rb +24 -0
- data/lib/mocha/integration/test_unit/adapter.rb +50 -0
- data/lib/mocha/integration/test_unit/gem_version_200.rb +39 -29
- data/lib/mocha/integration/test_unit/gem_version_201_to_202.rb +39 -29
- data/lib/mocha/integration/test_unit/gem_version_203_to_220.rb +39 -29
- data/lib/mocha/integration/test_unit/gem_version_230_to_250.rb +68 -0
- data/lib/mocha/integration/test_unit/nothing.rb +19 -0
- data/lib/mocha/integration/test_unit/ruby_version_185_and_below.rb +39 -29
- data/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb +40 -30
- data/lib/mocha/integration/test_unit.rb +45 -51
- data/lib/mocha/integration.rb +6 -33
- data/lib/mocha/invocation.rb +77 -0
- data/lib/mocha/is_a.rb +0 -2
- data/lib/mocha/logger.rb +2 -6
- data/lib/mocha/macos_version.rb +5 -0
- data/lib/mocha/method_matcher.rb +6 -10
- data/lib/mocha/minitest.rb +8 -0
- data/lib/mocha/mock.rb +266 -79
- data/lib/mocha/mockery.rb +104 -106
- data/lib/mocha/names.rb +10 -20
- data/lib/mocha/not_initialized_error.rb +7 -0
- data/lib/mocha/object_methods.rb +169 -0
- data/lib/mocha/parameter_matchers/all_of.rb +18 -14
- data/lib/mocha/parameter_matchers/any_of.rb +19 -14
- data/lib/mocha/parameter_matchers/any_parameters.rb +14 -13
- data/lib/mocha/parameter_matchers/anything.rb +17 -14
- data/lib/mocha/parameter_matchers/base.rb +33 -31
- data/lib/mocha/parameter_matchers/equals.rb +18 -13
- data/lib/mocha/parameter_matchers/equivalent_uri.rb +58 -0
- data/lib/mocha/parameter_matchers/has_entries.rb +19 -14
- data/lib/mocha/parameter_matchers/has_entry.rb +58 -26
- data/lib/mocha/parameter_matchers/has_key.rb +18 -13
- data/lib/mocha/parameter_matchers/has_keys.rb +53 -0
- data/lib/mocha/parameter_matchers/has_value.rb +18 -13
- data/lib/mocha/parameter_matchers/includes.rb +80 -19
- data/lib/mocha/parameter_matchers/instance_methods.rb +18 -0
- data/lib/mocha/parameter_matchers/instance_of.rb +18 -13
- data/lib/mocha/parameter_matchers/is_a.rb +20 -14
- data/lib/mocha/parameter_matchers/kind_of.rb +20 -13
- data/lib/mocha/parameter_matchers/not.rb +19 -14
- data/lib/mocha/parameter_matchers/optionally.rb +23 -17
- data/lib/mocha/parameter_matchers/regexp_matches.rb +16 -12
- data/lib/mocha/parameter_matchers/responds_with.rb +17 -11
- data/lib/mocha/parameter_matchers/yaml_equivalent.rb +15 -9
- data/lib/mocha/parameter_matchers.rb +4 -5
- data/lib/mocha/parameters_matcher.rb +11 -14
- data/lib/mocha/raised_exception.rb +11 -0
- data/lib/mocha/receivers.rb +45 -0
- data/lib/mocha/return_values.rb +11 -15
- data/lib/mocha/ruby_version.rb +4 -0
- data/lib/mocha/sequence.rb +21 -17
- data/lib/mocha/setup.rb +14 -0
- data/lib/mocha/single_return_value.rb +5 -8
- data/lib/mocha/singleton_class.rb +9 -0
- data/lib/mocha/state_machine.rb +69 -67
- data/lib/mocha/stubbed_method.rb +125 -0
- data/lib/mocha/stubbing_error.rb +6 -14
- data/lib/mocha/test_unit.rb +8 -0
- data/lib/mocha/thrower.rb +6 -8
- data/lib/mocha/thrown_object.rb +12 -0
- data/lib/mocha/version.rb +1 -1
- data/lib/mocha/yield_parameters.rb +12 -22
- data/lib/mocha.rb +8 -3
- data/mocha.gemspec +43 -34
- data/yard-templates/default/layout/html/google_analytics.erb +8 -0
- data/yard-templates/default/layout/html/setup.rb +5 -0
- metadata +123 -268
- data/COPYING.rdoc +0 -3
- data/README.rdoc +0 -54
- data/examples/misc.rb +0 -43
- data/examples/mocha.rb +0 -25
- data/examples/stubba.rb +0 -64
- 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.3.0 +0 -7
- data/gemfiles/Gemfile.test-unit.2.0.0 +0 -8
- 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 -98
- data/lib/mocha/integration/mini_test/assertion_counter.rb +0 -23
- data/lib/mocha/integration/mini_test/version_230_to_262.rb +0 -59
- data/lib/mocha/integration/test_unit/assertion_counter.rb +0 -23
- data/lib/mocha/integration/test_unit/gem_version_230_to_240.rb +0 -58
- data/lib/mocha/module_method.rb +0 -16
- data/lib/mocha/multiple_yields.rb +0 -20
- data/lib/mocha/no_yields.rb +0 -11
- data/lib/mocha/object.rb +0 -223
- data/lib/mocha/options.rb +0 -1
- data/lib/mocha/parameter_matchers/object.rb +0 -15
- data/lib/mocha/parameter_matchers/query_string.rb +0 -47
- data/lib/mocha/pretty_parameters.rb +0 -28
- data/lib/mocha/single_yield.rb +0 -18
- data/lib/mocha/standalone.rb +0 -1
- data/lib/mocha/unexpected_invocation.rb +0 -18
- data/lib/mocha_standalone.rb +0 -2
- data/lib/stubba.rb +0 -4
- data/test/acceptance/acceptance_test_helper.rb +0 -41
- data/test/acceptance/api_test.rb +0 -139
- 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_65_test.rb +0 -63
- data/test/acceptance/issue_70_test.rb +0 -55
- data/test/acceptance/minitest_test.rb +0 -162
- 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 -300
- data/test/acceptance/partial_mocks_test.rb +0 -47
- 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_test.rb +0 -198
- 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 -72
- 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 -75
- 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 -66
- 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 -75
- 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_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.rb +0 -15
- data/test/acceptance/stubba_test_result_test.rb +0 -66
- data/test/acceptance/stubbing_error_backtrace_test.rb +0 -64
- data/test/acceptance/stubbing_method_unnecessarily_test.rb +0 -65
- data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +0 -130
- 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/throw_test.rb +0 -45
- data/test/acceptance/unstubbing_test.rb +0 -151
- data/test/deprecation_disabler.rb +0 -15
- data/test/execution_point.rb +0 -36
- data/test/method_definer.rb +0 -24
- data/test/mini_test_result.rb +0 -83
- data/test/simple_counter.rb +0 -13
- data/test/test_helper.rb +0 -11
- data/test/test_runner.rb +0 -50
- 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 -260
- 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 -71
- data/test/unit/expectation_test.rb +0 -480
- data/test/unit/hash_inspect_test.rb +0 -16
- data/test/unit/in_state_ordering_constraint_test.rb +0 -43
- data/test/unit/method_matcher_test.rb +0 -23
- data/test/unit/mock_test.rb +0 -312
- data/test/unit/mockery_test.rb +0 -150
- 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 -38
- data/test/unit/object_test.rb +0 -87
- 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 -96
- 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 -44
- 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 -25
- 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/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/mockery.rb
CHANGED
@@ -1,181 +1,179 @@
|
|
1
|
+
require 'mocha/ruby_version'
|
1
2
|
require 'mocha/central'
|
2
3
|
require 'mocha/mock'
|
3
4
|
require 'mocha/names'
|
5
|
+
require 'mocha/receivers'
|
4
6
|
require 'mocha/state_machine'
|
5
7
|
require 'mocha/logger'
|
6
8
|
require 'mocha/configuration'
|
7
9
|
require 'mocha/stubbing_error'
|
10
|
+
require 'mocha/not_initialized_error'
|
11
|
+
require 'mocha/expectation_error_factory'
|
8
12
|
|
9
13
|
module Mocha
|
10
|
-
|
11
14
|
class Mockery
|
12
|
-
|
15
|
+
class Null < self
|
16
|
+
def add_mock(*)
|
17
|
+
raise_not_initialized_error
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_state_machine(*)
|
21
|
+
raise_not_initialized_error
|
22
|
+
end
|
23
|
+
|
24
|
+
def stubba
|
25
|
+
Central::Null.new(&method(:raise_not_initialized_error))
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def raise_not_initialized_error
|
31
|
+
message = 'Mocha methods cannot be used outside the context of a test'
|
32
|
+
raise NotInitializedError.new(message, caller)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
13
36
|
class << self
|
14
|
-
|
15
37
|
def instance
|
16
|
-
@
|
38
|
+
@instances.last || Null.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
@instances ||= []
|
43
|
+
mockery = new
|
44
|
+
mockery.logger = instance.logger unless @instances.empty?
|
45
|
+
@instances.push(mockery)
|
46
|
+
end
|
47
|
+
|
48
|
+
def verify(*args)
|
49
|
+
instance.verify(*args)
|
17
50
|
end
|
18
|
-
|
19
|
-
def
|
20
|
-
|
51
|
+
|
52
|
+
def teardown
|
53
|
+
instance.teardown
|
54
|
+
ensure
|
55
|
+
@instances.pop
|
21
56
|
end
|
22
|
-
|
23
57
|
end
|
24
|
-
|
25
|
-
def named_mock(name
|
26
|
-
add_mock(Mock.new(self, Name.new(name)
|
58
|
+
|
59
|
+
def named_mock(name)
|
60
|
+
add_mock(Mock.new(self, Name.new(name)))
|
27
61
|
end
|
28
|
-
|
29
|
-
def unnamed_mock
|
30
|
-
add_mock(Mock.new(self
|
62
|
+
|
63
|
+
def unnamed_mock
|
64
|
+
add_mock(Mock.new(self))
|
31
65
|
end
|
32
|
-
|
33
|
-
def mock_impersonating(object
|
34
|
-
add_mock(Mock.new(self, ImpersonatingName.new(object),
|
66
|
+
|
67
|
+
def mock_impersonating(object)
|
68
|
+
add_mock(Mock.new(self, ImpersonatingName.new(object), ObjectReceiver.new(object)))
|
35
69
|
end
|
36
|
-
|
37
|
-
def mock_impersonating_any_instance_of(klass
|
38
|
-
add_mock(Mock.new(self, ImpersonatingAnyInstanceName.new(klass),
|
70
|
+
|
71
|
+
def mock_impersonating_any_instance_of(klass)
|
72
|
+
add_mock(Mock.new(self, ImpersonatingAnyInstanceName.new(klass), AnyInstanceReceiver.new(klass)))
|
39
73
|
end
|
40
|
-
|
74
|
+
|
41
75
|
def new_state_machine(name)
|
42
76
|
add_state_machine(StateMachine.new(name))
|
43
77
|
end
|
44
|
-
|
78
|
+
|
45
79
|
def verify(assertion_counter = nil)
|
46
80
|
unless mocks.all? { |mock| mock.__verified__?(assertion_counter) }
|
47
81
|
message = "not all expectations were satisfied\n#{mocha_inspect}"
|
48
|
-
if unsatisfied_expectations.empty?
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
raise
|
82
|
+
backtrace = if unsatisfied_expectations.empty?
|
83
|
+
caller
|
84
|
+
else
|
85
|
+
unsatisfied_expectations[0].backtrace
|
86
|
+
end
|
87
|
+
raise ExpectationErrorFactory.build(message, backtrace)
|
54
88
|
end
|
55
|
-
expectations.each do |
|
56
|
-
|
57
|
-
|
58
|
-
on_stubbing_method_unnecessarily(e)
|
59
|
-
end
|
60
|
-
end
|
89
|
+
expectations.reject(&:used?).each do |expectation|
|
90
|
+
signature_proc = lambda { expectation.method_signature }
|
91
|
+
check(:stubbing_method_unnecessarily, 'method unnecessarily', signature_proc, expectation.backtrace)
|
61
92
|
end
|
62
93
|
end
|
63
|
-
|
94
|
+
|
64
95
|
def teardown
|
65
96
|
stubba.unstub_all
|
97
|
+
mocks.each(&:__expire__)
|
66
98
|
reset
|
67
99
|
end
|
68
|
-
|
100
|
+
|
69
101
|
def stubba
|
70
102
|
@stubba ||= Central.new
|
71
103
|
end
|
72
|
-
|
104
|
+
|
73
105
|
def mocks
|
74
106
|
@mocks ||= []
|
75
107
|
end
|
76
|
-
|
108
|
+
|
77
109
|
def state_machines
|
78
110
|
@state_machines ||= []
|
79
111
|
end
|
80
|
-
|
112
|
+
|
81
113
|
def mocha_inspect
|
82
|
-
message =
|
83
|
-
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map
|
84
|
-
message << "satisfied expectations:\n- #{satisfied_expectations.map
|
85
|
-
message << "states:\n- #{state_machines.map
|
114
|
+
message = ''
|
115
|
+
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n" if unsatisfied_expectations.any?
|
116
|
+
message << "satisfied expectations:\n- #{satisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n" if satisfied_expectations.any?
|
117
|
+
message << "states:\n- #{state_machines.map(&:mocha_inspect).join("\n- ")}\n" if state_machines.any?
|
86
118
|
message
|
87
119
|
end
|
88
|
-
|
120
|
+
|
89
121
|
def on_stubbing(object, method)
|
90
|
-
method =
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
95
|
-
end
|
96
|
-
unless Mocha::Configuration.allow?(:stubbing_non_public_method)
|
97
|
-
if object.method_exists?(method, include_public_methods = false)
|
98
|
-
on_stubbing_non_public_method(object, method)
|
99
|
-
end
|
122
|
+
method = PRE_RUBY_V19 ? method.to_s : method.to_sym
|
123
|
+
signature_proc = lambda { "#{object.mocha_inspect}.#{method}" }
|
124
|
+
check(:stubbing_non_existent_method, 'non-existent method', signature_proc) do
|
125
|
+
!(object.stubba_class.__method_exists__?(method, true) || object.respond_to?(method.to_sym))
|
100
126
|
end
|
101
|
-
|
102
|
-
|
127
|
+
check(:stubbing_non_public_method, 'non-public method', signature_proc) do
|
128
|
+
object.stubba_class.__method_exists__?(method, false)
|
103
129
|
end
|
130
|
+
check(:stubbing_method_on_nil, 'method on nil', signature_proc) { object.nil? }
|
131
|
+
check(:stubbing_method_on_non_mock_object, 'method on non-mock object', signature_proc)
|
104
132
|
end
|
105
|
-
|
106
|
-
def on_stubbing_non_existent_method(object, method)
|
107
|
-
if Mocha::Configuration.prevent?(:stubbing_non_existent_method)
|
108
|
-
raise StubbingError.new("stubbing non-existent method: #{object.mocha_inspect}.#{method}", caller)
|
109
|
-
end
|
110
|
-
if Mocha::Configuration.warn_when?(:stubbing_non_existent_method)
|
111
|
-
logger.warn "stubbing non-existent method: #{object.mocha_inspect}.#{method}"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def on_stubbing_non_public_method(object, method)
|
116
|
-
if Mocha::Configuration.prevent?(:stubbing_non_public_method)
|
117
|
-
raise StubbingError.new("stubbing non-public method: #{object.mocha_inspect}.#{method}", caller)
|
118
|
-
end
|
119
|
-
if Mocha::Configuration.warn_when?(:stubbing_non_public_method)
|
120
|
-
logger.warn "stubbing non-public method: #{object.mocha_inspect}.#{method}"
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def on_stubbing_method_on_non_mock_object(object, method)
|
125
|
-
if Mocha::Configuration.prevent?(:stubbing_method_on_non_mock_object)
|
126
|
-
raise StubbingError.new("stubbing method on non-mock object: #{object.mocha_inspect}.#{method}", caller)
|
127
|
-
end
|
128
|
-
if Mocha::Configuration.warn_when?(:stubbing_method_on_non_mock_object)
|
129
|
-
logger.warn "stubbing method on non-mock object: #{object.mocha_inspect}.#{method}"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def on_stubbing_method_unnecessarily(expectation)
|
134
|
-
if Mocha::Configuration.prevent?(:stubbing_method_unnecessarily)
|
135
|
-
raise StubbingError.new("stubbing method unnecessarily: #{expectation.method_signature}", expectation.backtrace)
|
136
|
-
end
|
137
|
-
if Mocha::Configuration.warn_when?(:stubbing_method_unnecessarily)
|
138
|
-
logger.warn "stubbing method unnecessarily: #{expectation.method_signature}"
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
133
|
+
|
142
134
|
attr_writer :logger
|
143
|
-
|
135
|
+
|
144
136
|
def logger
|
145
137
|
@logger ||= Logger.new($stderr)
|
146
138
|
end
|
147
|
-
|
148
|
-
|
139
|
+
|
149
140
|
private
|
150
|
-
|
141
|
+
|
142
|
+
def check(action, description, signature_proc, backtrace = caller)
|
143
|
+
treatment = Mocha.configuration.send(action)
|
144
|
+
return if (treatment == :allow) || (block_given? && !yield)
|
145
|
+
method_signature = signature_proc.call
|
146
|
+
message = "stubbing #{description}: #{method_signature}"
|
147
|
+
raise StubbingError.new(message, backtrace) if treatment == :prevent
|
148
|
+
logger.warn(message) if treatment == :warn
|
149
|
+
end
|
150
|
+
|
151
151
|
def expectations
|
152
152
|
mocks.map { |mock| mock.__expectations__.to_a }.flatten
|
153
153
|
end
|
154
|
-
|
154
|
+
|
155
155
|
def unsatisfied_expectations
|
156
|
-
expectations.reject
|
156
|
+
expectations.reject(&:verified?)
|
157
157
|
end
|
158
|
-
|
158
|
+
|
159
159
|
def satisfied_expectations
|
160
|
-
expectations.select
|
160
|
+
expectations.select(&:verified?)
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
def add_mock(mock)
|
164
164
|
mocks << mock
|
165
165
|
mock
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
def add_state_machine(state_machine)
|
169
169
|
state_machines << state_machine
|
170
170
|
state_machine
|
171
171
|
end
|
172
|
-
|
172
|
+
|
173
173
|
def reset
|
174
174
|
@stubba = nil
|
175
175
|
@mocks = nil
|
176
176
|
@state_machines = nil
|
177
177
|
end
|
178
|
-
|
179
178
|
end
|
180
|
-
|
181
179
|
end
|
data/lib/mocha/names.rb
CHANGED
@@ -1,53 +1,43 @@
|
|
1
1
|
module Mocha
|
2
|
-
|
3
2
|
class ImpersonatingName
|
4
|
-
|
5
3
|
def initialize(object)
|
6
4
|
@object = object
|
7
5
|
end
|
8
|
-
|
6
|
+
|
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
|
20
|
-
|
16
|
+
|
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
|
44
|
-
|
36
|
+
|
45
37
|
def mocha_inspect
|
46
38
|
address = @mock.__id__ * 2
|
47
39
|
address += 0x100000000 if address < 0
|
48
|
-
"#<Mock:0x#{'%x'
|
40
|
+
"#<Mock:0x#{format('%x', address)}>"
|
49
41
|
end
|
50
|
-
|
51
42
|
end
|
52
|
-
|
53
|
-
end
|
43
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'mocha/mockery'
|
2
|
+
require 'mocha/instance_method'
|
3
|
+
require 'mocha/argument_iterator'
|
4
|
+
require 'mocha/expectation_error_factory'
|
5
|
+
|
6
|
+
module Mocha
|
7
|
+
# Methods added to all objects to allow mocking and stubbing on real (i.e. non-mock) objects.
|
8
|
+
#
|
9
|
+
# Both {#expects} and {#stubs} return an {Expectation} which can be further modified by methods on {Expectation}.
|
10
|
+
module ObjectMethods
|
11
|
+
# @private
|
12
|
+
alias_method :_method, :method
|
13
|
+
|
14
|
+
# @private
|
15
|
+
def mocha(instantiate = true)
|
16
|
+
if instantiate
|
17
|
+
@mocha ||= Mocha::Mockery.instance.mock_impersonating(self)
|
18
|
+
else
|
19
|
+
defined?(@mocha) ? @mocha : nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @private
|
24
|
+
def reset_mocha
|
25
|
+
@mocha = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
# @private
|
29
|
+
def stubba_method
|
30
|
+
Mocha::InstanceMethod
|
31
|
+
end
|
32
|
+
|
33
|
+
# @private
|
34
|
+
def stubba_object
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# @private
|
39
|
+
def stubba_class
|
40
|
+
singleton_class
|
41
|
+
end
|
42
|
+
|
43
|
+
# Adds an expectation that the specified method must be called exactly once with any parameters.
|
44
|
+
#
|
45
|
+
# The original implementation of the method is replaced during the test and then restored at the end of the test. The temporary replacement method has the same visibility as the original method.
|
46
|
+
#
|
47
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
48
|
+
# @raise [StubbingError] if attempting to stub method which is not allowed.
|
49
|
+
#
|
50
|
+
# @overload def expects(method_name)
|
51
|
+
# @param [Symbol,String] method_name name of expected method
|
52
|
+
# @overload def expects(expected_methods_vs_return_values)
|
53
|
+
# @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {#expects} were called multiple times.
|
54
|
+
#
|
55
|
+
# @example Setting up an expectation on a non-mock object.
|
56
|
+
# product = Product.new
|
57
|
+
# product.expects(:save).returns(true)
|
58
|
+
# assert_equal true, product.save
|
59
|
+
#
|
60
|
+
# @example Setting up multiple expectations on a non-mock object.
|
61
|
+
# product = Product.new
|
62
|
+
# product.expects(:valid? => true, :save => true)
|
63
|
+
#
|
64
|
+
# # exactly equivalent to
|
65
|
+
#
|
66
|
+
# product = Product.new
|
67
|
+
# product.expects(:valid?).returns(true)
|
68
|
+
# product.expects(:save).returns(true)
|
69
|
+
#
|
70
|
+
# @see Mock#expects
|
71
|
+
def expects(expected_methods_vs_return_values)
|
72
|
+
if expected_methods_vs_return_values.to_s =~ /the[^a-z]*spanish[^a-z]*inquisition/i
|
73
|
+
raise ExpectationErrorFactory.build('NOBODY EXPECTS THE SPANISH INQUISITION!')
|
74
|
+
end
|
75
|
+
if frozen?
|
76
|
+
raise StubbingError.new("can't stub method on frozen object: #{mocha_inspect}", caller)
|
77
|
+
end
|
78
|
+
expectation = nil
|
79
|
+
mockery = Mocha::Mockery.instance
|
80
|
+
iterator = ArgumentIterator.new(expected_methods_vs_return_values)
|
81
|
+
iterator.each do |*args|
|
82
|
+
method_name = args.shift
|
83
|
+
mockery.on_stubbing(self, method_name)
|
84
|
+
method = stubba_method.new(stubba_object, method_name)
|
85
|
+
mockery.stubba.stub(method)
|
86
|
+
expectation = mocha.expects(method_name, caller)
|
87
|
+
expectation.returns(args.shift) unless args.empty?
|
88
|
+
end
|
89
|
+
expectation
|
90
|
+
end
|
91
|
+
|
92
|
+
# Adds an expectation that the specified method may be called any number of times with any parameters.
|
93
|
+
#
|
94
|
+
# The original implementation of the method is replaced during the test and then restored at the end of the test. The temporary replacement method has the same visibility as the original method.
|
95
|
+
#
|
96
|
+
# @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}.
|
97
|
+
# @raise [StubbingError] if attempting to stub method which is not allowed.
|
98
|
+
#
|
99
|
+
# @overload def stubs(method_name)
|
100
|
+
# @param [Symbol,String] method_name name of stubbed method
|
101
|
+
# @overload def stubs(stubbed_methods_vs_return_values)
|
102
|
+
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {#stubs} were called multiple times.
|
103
|
+
#
|
104
|
+
# @example Setting up a stubbed methods on a non-mock object.
|
105
|
+
# product = Product.new
|
106
|
+
# product.stubs(:save).returns(true)
|
107
|
+
# assert_equal true, product.save
|
108
|
+
#
|
109
|
+
# @example Setting up multiple stubbed methods on a non-mock object.
|
110
|
+
# product = Product.new
|
111
|
+
# product.stubs(:valid? => true, :save => true)
|
112
|
+
#
|
113
|
+
# # exactly equivalent to
|
114
|
+
#
|
115
|
+
# product = Product.new
|
116
|
+
# product.stubs(:valid?).returns(true)
|
117
|
+
# product.stubs(:save).returns(true)
|
118
|
+
#
|
119
|
+
# @see Mock#stubs
|
120
|
+
def stubs(stubbed_methods_vs_return_values)
|
121
|
+
if frozen?
|
122
|
+
raise StubbingError.new("can't stub method on frozen object: #{mocha_inspect}", caller)
|
123
|
+
end
|
124
|
+
expectation = nil
|
125
|
+
mockery = Mocha::Mockery.instance
|
126
|
+
iterator = ArgumentIterator.new(stubbed_methods_vs_return_values)
|
127
|
+
iterator.each do |*args|
|
128
|
+
method_name = args.shift
|
129
|
+
mockery.on_stubbing(self, method_name)
|
130
|
+
method = stubba_method.new(stubba_object, method_name)
|
131
|
+
mockery.stubba.stub(method)
|
132
|
+
expectation = mocha.stubs(method_name, caller)
|
133
|
+
expectation.returns(args.shift) unless args.empty?
|
134
|
+
end
|
135
|
+
expectation
|
136
|
+
end
|
137
|
+
|
138
|
+
# Removes the specified stubbed methods (added by calls to {#expects} or {#stubs}) and all expectations associated with them.
|
139
|
+
#
|
140
|
+
# Restores the original behaviour of the methods before they were stubbed. This is normally done automatically at the end of each test, but in some circumstances you may want to do it *before* the end of the test.
|
141
|
+
#
|
142
|
+
# WARNING: If you {#unstub} a method which still has unsatisfied expectations, you may be removing the only way those expectations can be satisfied. Use {#unstub} with care.
|
143
|
+
#
|
144
|
+
# @param [Array<Symbol>] method_names names of methods to unstub.
|
145
|
+
#
|
146
|
+
# @example Stubbing and unstubbing a method on a real (non-mock) object.
|
147
|
+
# multiplier = Multiplier.new
|
148
|
+
# multiplier.double(2) # => 4
|
149
|
+
# multiplier.stubs(:double).raises # new behaviour defined
|
150
|
+
# multiplier.double(2) # => raises exception
|
151
|
+
# multiplier.unstub(:double) # original behaviour restored
|
152
|
+
# multiplier.double(2) # => 4
|
153
|
+
#
|
154
|
+
# @example Unstubbing multiple methods on a real (non-mock) object.
|
155
|
+
# multiplier.unstub(:double, :triple)
|
156
|
+
#
|
157
|
+
# # exactly equivalent to
|
158
|
+
#
|
159
|
+
# multiplier.unstub(:double)
|
160
|
+
# multiplier.unstub(:triple)
|
161
|
+
def unstub(*method_names)
|
162
|
+
mockery = Mocha::Mockery.instance
|
163
|
+
method_names.each do |method_name|
|
164
|
+
method = stubba_method.new(stubba_object, method_name)
|
165
|
+
mockery.stubba.unstub(method)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -1,17 +1,21 @@
|
|
1
1
|
require 'mocha/parameter_matchers/base'
|
2
2
|
|
3
3
|
module Mocha
|
4
|
-
|
5
4
|
module ParameterMatchers
|
6
|
-
|
7
|
-
#
|
5
|
+
# Matches if all +matchers+ match.
|
6
|
+
#
|
7
|
+
# @param [*Array<Base>] matchers parameter matchers.
|
8
|
+
# @return [AllOf] parameter matcher.
|
9
|
+
#
|
10
|
+
# @see Expectation#with
|
8
11
|
#
|
9
|
-
#
|
12
|
+
# @example All parameter matchers match.
|
10
13
|
# object = mock()
|
11
14
|
# object.expects(:method_1).with(all_of(includes(1), includes(3)))
|
12
15
|
# object.method_1([1, 3])
|
13
16
|
# # no error raised
|
14
17
|
#
|
18
|
+
# @example One of the parameter matchers does not match.
|
15
19
|
# object = mock()
|
16
20
|
# object.expects(:method_1).with(all_of(includes(1), includes(3)))
|
17
21
|
# object.method_1([1, 2])
|
@@ -19,24 +23,24 @@ module Mocha
|
|
19
23
|
def all_of(*matchers)
|
20
24
|
AllOf.new(*matchers)
|
21
25
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
|
27
|
+
# Parameter matcher which combines a number of other matchers using a logical AND.
|
28
|
+
class AllOf < Base
|
29
|
+
# @private
|
25
30
|
def initialize(*matchers)
|
26
31
|
@matchers = matchers
|
27
32
|
end
|
28
|
-
|
33
|
+
|
34
|
+
# @private
|
29
35
|
def matches?(available_parameters)
|
30
36
|
parameter = available_parameters.shift
|
31
37
|
@matchers.all? { |matcher| matcher.to_matcher.matches?([parameter]) }
|
32
38
|
end
|
33
|
-
|
39
|
+
|
40
|
+
# @private
|
34
41
|
def mocha_inspect
|
35
|
-
"all_of(#{@matchers.map
|
42
|
+
"all_of(#{@matchers.map(&:mocha_inspect).join(', ')})"
|
36
43
|
end
|
37
|
-
|
38
44
|
end
|
39
|
-
|
40
45
|
end
|
41
|
-
|
42
|
-
end
|
46
|
+
end
|
@@ -1,22 +1,27 @@
|
|
1
1
|
require 'mocha/parameter_matchers/base'
|
2
2
|
|
3
3
|
module Mocha
|
4
|
-
|
5
4
|
module ParameterMatchers
|
6
|
-
|
7
|
-
#
|
5
|
+
# Matches if any +matchers+ match.
|
6
|
+
#
|
7
|
+
# @param [*Array<Base>] matchers parameter matchers.
|
8
|
+
# @return [AnyOf] parameter matcher.
|
9
|
+
#
|
10
|
+
# @see Expectation#with
|
8
11
|
#
|
9
|
-
#
|
12
|
+
# @example One parameter matcher matches.
|
10
13
|
# object = mock()
|
11
14
|
# object.expects(:method_1).with(any_of(1, 3))
|
12
15
|
# object.method_1(1)
|
13
16
|
# # no error raised
|
14
17
|
#
|
18
|
+
# @example The other parameter matcher matches.
|
15
19
|
# object = mock()
|
16
20
|
# object.expects(:method_1).with(any_of(1, 3))
|
17
21
|
# object.method_1(3)
|
18
22
|
# # no error raised
|
19
23
|
#
|
24
|
+
# @example Neither parameter matcher matches.
|
20
25
|
# object = mock()
|
21
26
|
# object.expects(:method_1).with(any_of(1, 3))
|
22
27
|
# object.method_1(2)
|
@@ -24,24 +29,24 @@ module Mocha
|
|
24
29
|
def any_of(*matchers)
|
25
30
|
AnyOf.new(*matchers)
|
26
31
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
|
33
|
+
# Parameter matcher which combines a number of other matchers using a logical OR.
|
34
|
+
class AnyOf < Base
|
35
|
+
# @private
|
30
36
|
def initialize(*matchers)
|
31
37
|
@matchers = matchers
|
32
38
|
end
|
33
|
-
|
39
|
+
|
40
|
+
# @private
|
34
41
|
def matches?(available_parameters)
|
35
42
|
parameter = available_parameters.shift
|
36
43
|
@matchers.any? { |matcher| matcher.to_matcher.matches?([parameter]) }
|
37
44
|
end
|
38
|
-
|
45
|
+
|
46
|
+
# @private
|
39
47
|
def mocha_inspect
|
40
|
-
"any_of(#{@matchers.map
|
48
|
+
"any_of(#{@matchers.map(&:mocha_inspect).join(', ')})"
|
41
49
|
end
|
42
|
-
|
43
50
|
end
|
44
|
-
|
45
51
|
end
|
46
|
-
|
47
|
-
end
|
52
|
+
end
|