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.
Files changed (266) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +1 -0
  3. data/.rubocop.yml +65 -0
  4. data/.rubocop_todo.yml +27 -0
  5. data/.yardopts +1 -0
  6. data/CONTRIBUTING.md +4 -9
  7. data/Gemfile +29 -0
  8. data/README.md +110 -106
  9. data/RELEASE.md +306 -1
  10. data/Rakefile +52 -45
  11. data/gemfiles/Gemfile.minitest.latest +1 -0
  12. data/gemfiles/Gemfile.test-unit.latest +2 -5
  13. data/lib/mocha/any_instance_method.rb +9 -62
  14. data/lib/mocha/api.rb +84 -68
  15. data/lib/mocha/argument_iterator.rb +4 -8
  16. data/lib/mocha/backtrace_filter.rb +1 -5
  17. data/lib/mocha/block_matcher.rb +31 -0
  18. data/lib/mocha/cardinality.rb +60 -49
  19. data/lib/mocha/central.rb +21 -12
  20. data/lib/mocha/change_state_side_effect.rb +0 -4
  21. data/lib/mocha/class_methods.rb +19 -21
  22. data/lib/mocha/configuration.rb +312 -47
  23. data/lib/mocha/debug.rb +3 -2
  24. data/lib/mocha/deprecation.rb +8 -11
  25. data/lib/mocha/detection/mini_test.rb +0 -2
  26. data/lib/mocha/detection/test_unit.rb +3 -5
  27. data/lib/mocha/error_with_filtered_backtrace.rb +13 -0
  28. data/lib/mocha/exception_raiser.rb +4 -6
  29. data/lib/mocha/expectation.rb +186 -95
  30. data/lib/mocha/expectation_error.rb +1 -1
  31. data/lib/mocha/expectation_error_factory.rb +0 -1
  32. data/lib/mocha/expectation_list.rb +7 -11
  33. data/lib/mocha/hooks.rb +1 -3
  34. data/lib/mocha/in_state_ordering_constraint.rb +0 -4
  35. data/lib/mocha/inspect.rb +30 -38
  36. data/lib/mocha/instance_method.rb +11 -8
  37. data/lib/mocha/integration/mini_test/adapter.rb +2 -4
  38. data/lib/mocha/integration/mini_test/exception_translation.rb +1 -1
  39. data/lib/mocha/integration/mini_test.rb +10 -31
  40. data/lib/mocha/integration/monkey_patcher.rb +5 -7
  41. data/lib/mocha/integration/test_unit/adapter.rb +5 -6
  42. data/lib/mocha/integration/test_unit.rb +10 -26
  43. data/lib/mocha/invocation.rb +73 -0
  44. data/lib/mocha/is_a.rb +0 -2
  45. data/lib/mocha/logger.rb +0 -4
  46. data/lib/mocha/macos_version.rb +5 -0
  47. data/lib/mocha/method_matcher.rb +1 -5
  48. data/lib/mocha/minitest.rb +6 -0
  49. data/lib/mocha/mock.rb +99 -51
  50. data/lib/mocha/mockery.rb +70 -99
  51. data/lib/mocha/names.rb +2 -12
  52. data/lib/mocha/not_initialized_error.rb +7 -0
  53. data/lib/mocha/object_methods.rb +25 -31
  54. data/lib/mocha/parameter_matchers/all_of.rb +2 -8
  55. data/lib/mocha/parameter_matchers/any_of.rb +2 -8
  56. data/lib/mocha/parameter_matchers/any_parameters.rb +3 -9
  57. data/lib/mocha/parameter_matchers/anything.rb +2 -8
  58. data/lib/mocha/parameter_matchers/base.rb +7 -13
  59. data/lib/mocha/parameter_matchers/equals.rb +0 -6
  60. data/lib/mocha/parameter_matchers/{query_string.rb → equivalent_uri.rb} +14 -15
  61. data/lib/mocha/parameter_matchers/has_entries.rb +2 -7
  62. data/lib/mocha/parameter_matchers/has_entry.rb +26 -21
  63. data/lib/mocha/parameter_matchers/has_key.rb +2 -7
  64. data/lib/mocha/parameter_matchers/has_keys.rb +53 -0
  65. data/lib/mocha/parameter_matchers/has_value.rb +2 -7
  66. data/lib/mocha/parameter_matchers/includes.rb +6 -7
  67. data/lib/mocha/parameter_matchers/instance_methods.rb +27 -0
  68. data/lib/mocha/parameter_matchers/instance_of.rb +0 -6
  69. data/lib/mocha/parameter_matchers/is_a.rb +2 -7
  70. data/lib/mocha/parameter_matchers/kind_of.rb +2 -6
  71. data/lib/mocha/parameter_matchers/not.rb +2 -7
  72. data/lib/mocha/parameter_matchers/optionally.rb +4 -10
  73. data/lib/mocha/parameter_matchers/positional_or_keyword_hash.rb +64 -0
  74. data/lib/mocha/parameter_matchers/regexp_matches.rb +0 -6
  75. data/lib/mocha/parameter_matchers/responds_with.rb +3 -8
  76. data/lib/mocha/parameter_matchers/yaml_equivalent.rb +2 -6
  77. data/lib/mocha/parameter_matchers.rb +3 -4
  78. data/lib/mocha/parameters_matcher.rb +8 -11
  79. data/lib/mocha/raised_exception.rb +11 -0
  80. data/lib/mocha/receivers.rb +10 -14
  81. data/lib/mocha/return_values.rb +4 -8
  82. data/lib/mocha/ruby_version.rb +1 -2
  83. data/lib/mocha/sequence.rb +4 -9
  84. data/lib/mocha/single_return_value.rb +2 -5
  85. data/lib/mocha/state_machine.rb +33 -46
  86. data/lib/mocha/stubbed_method.rb +88 -0
  87. data/lib/mocha/stubbing_error.rb +2 -13
  88. data/lib/mocha/test_unit.rb +5 -2
  89. data/lib/mocha/thrower.rb +4 -6
  90. data/lib/mocha/thrown_object.rb +12 -0
  91. data/lib/mocha/version.rb +1 -1
  92. data/lib/mocha/yield_parameters.rb +7 -17
  93. data/mocha.gemspec +14 -65
  94. data/yard-templates/default/layout/html/google_analytics.erb +6 -9
  95. data/yard-templates/default/layout/html/setup.rb +2 -3
  96. metadata +26 -266
  97. data/bin/build-matrix +0 -70
  98. data/gemfiles/Gemfile.minitest.1.3.0 +0 -7
  99. data/gemfiles/Gemfile.minitest.1.4.0 +0 -7
  100. data/gemfiles/Gemfile.minitest.1.4.1 +0 -7
  101. data/gemfiles/Gemfile.minitest.1.4.2 +0 -7
  102. data/gemfiles/Gemfile.minitest.2.0.0 +0 -7
  103. data/gemfiles/Gemfile.minitest.2.0.1 +0 -7
  104. data/gemfiles/Gemfile.minitest.2.11.0 +0 -7
  105. data/gemfiles/Gemfile.minitest.2.11.2 +0 -7
  106. data/gemfiles/Gemfile.minitest.2.3.0 +0 -7
  107. data/gemfiles/Gemfile.test-unit.2.0.0 +0 -7
  108. data/gemfiles/Gemfile.test-unit.2.0.1 +0 -7
  109. data/gemfiles/Gemfile.test-unit.2.0.3 +0 -7
  110. data/init.rb +0 -3
  111. data/lib/mocha/class_method.rb +0 -119
  112. data/lib/mocha/integration/mini_test/nothing.rb +0 -19
  113. data/lib/mocha/integration/mini_test/version_13.rb +0 -51
  114. data/lib/mocha/integration/mini_test/version_140.rb +0 -51
  115. data/lib/mocha/integration/mini_test/version_141.rb +0 -62
  116. data/lib/mocha/integration/mini_test/version_142_to_172.rb +0 -62
  117. data/lib/mocha/integration/mini_test/version_200.rb +0 -63
  118. data/lib/mocha/integration/mini_test/version_201_to_222.rb +0 -63
  119. data/lib/mocha/integration/mini_test/version_2110_to_2111.rb +0 -67
  120. data/lib/mocha/integration/mini_test/version_2112_to_320.rb +0 -70
  121. data/lib/mocha/integration/mini_test/version_230_to_2101.rb +0 -65
  122. data/lib/mocha/integration/test_unit/gem_version_200.rb +0 -59
  123. data/lib/mocha/integration/test_unit/gem_version_201_to_202.rb +0 -59
  124. data/lib/mocha/integration/test_unit/gem_version_203_to_220.rb +0 -59
  125. data/lib/mocha/integration/test_unit/gem_version_230_to_250.rb +0 -65
  126. data/lib/mocha/integration/test_unit/nothing.rb +0 -19
  127. data/lib/mocha/integration/test_unit/ruby_version_185_and_below.rb +0 -58
  128. data/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb +0 -60
  129. data/lib/mocha/integration.rb +0 -14
  130. data/lib/mocha/mini_test.rb +0 -3
  131. data/lib/mocha/module_method.rb +0 -16
  132. data/lib/mocha/module_methods.rb +0 -14
  133. data/lib/mocha/multiple_yields.rb +0 -20
  134. data/lib/mocha/no_yields.rb +0 -11
  135. data/lib/mocha/parameter_matchers/object.rb +0 -17
  136. data/lib/mocha/pretty_parameters.rb +0 -28
  137. data/lib/mocha/setup.rb +0 -9
  138. data/lib/mocha/single_yield.rb +0 -18
  139. data/lib/mocha/standalone.rb +0 -4
  140. data/lib/mocha/unexpected_invocation.rb +0 -26
  141. data/lib/mocha_standalone.rb +0 -4
  142. data/test/acceptance/acceptance_test_helper.rb +0 -41
  143. data/test/acceptance/bug_18914_test.rb +0 -43
  144. data/test/acceptance/bug_21465_test.rb +0 -34
  145. data/test/acceptance/bug_21563_test.rb +0 -25
  146. data/test/acceptance/exception_rescue_test.rb +0 -55
  147. data/test/acceptance/expectations_on_multiple_methods_test.rb +0 -55
  148. data/test/acceptance/expected_invocation_count_test.rb +0 -232
  149. data/test/acceptance/failure_messages_test.rb +0 -64
  150. data/test/acceptance/issue_272_test.rb +0 -52
  151. data/test/acceptance/issue_65_test.rb +0 -63
  152. data/test/acceptance/issue_70_test.rb +0 -55
  153. data/test/acceptance/mocha_example_test.rb +0 -98
  154. data/test/acceptance/mocha_test_result_test.rb +0 -84
  155. data/test/acceptance/mock_test.rb +0 -100
  156. data/test/acceptance/mock_with_initializer_block_test.rb +0 -51
  157. data/test/acceptance/mocked_methods_dispatch_test.rb +0 -78
  158. data/test/acceptance/multiple_expectations_failure_message_test.rb +0 -68
  159. data/test/acceptance/optional_parameters_test.rb +0 -70
  160. data/test/acceptance/parameter_matcher_test.rb +0 -337
  161. data/test/acceptance/partial_mocks_test.rb +0 -47
  162. data/test/acceptance/prepend_test.rb +0 -89
  163. data/test/acceptance/raise_exception_test.rb +0 -39
  164. data/test/acceptance/return_value_test.rb +0 -52
  165. data/test/acceptance/sequence_test.rb +0 -192
  166. data/test/acceptance/states_test.rb +0 -70
  167. data/test/acceptance/stub_any_instance_method_defined_on_superclass_test.rb +0 -34
  168. data/test/acceptance/stub_any_instance_method_test.rb +0 -280
  169. data/test/acceptance/stub_class_method_defined_on_active_record_association_proxy_test.rb +0 -106
  170. data/test/acceptance/stub_class_method_defined_on_class_test.rb +0 -78
  171. data/test/acceptance/stub_class_method_defined_on_module_test.rb +0 -75
  172. data/test/acceptance/stub_class_method_defined_on_superclass_test.rb +0 -112
  173. data/test/acceptance/stub_everything_test.rb +0 -56
  174. data/test/acceptance/stub_instance_method_defined_on_active_record_association_proxy_test.rb +0 -93
  175. data/test/acceptance/stub_instance_method_defined_on_class_and_aliased_test.rb +0 -69
  176. data/test/acceptance/stub_instance_method_defined_on_class_test.rb +0 -69
  177. data/test/acceptance/stub_instance_method_defined_on_kernel_module_test.rb +0 -75
  178. data/test/acceptance/stub_instance_method_defined_on_module_test.rb +0 -78
  179. data/test/acceptance/stub_instance_method_defined_on_object_class_test.rb +0 -75
  180. data/test/acceptance/stub_instance_method_defined_on_singleton_class_test.rb +0 -70
  181. data/test/acceptance/stub_instance_method_defined_on_superclass_test.rb +0 -72
  182. data/test/acceptance/stub_method_defined_on_module_and_aliased_test.rb +0 -39
  183. data/test/acceptance/stub_module_method_test.rb +0 -163
  184. data/test/acceptance/stub_test.rb +0 -52
  185. data/test/acceptance/stubba_example_test.rb +0 -102
  186. data/test/acceptance/stubba_test_result_test.rb +0 -66
  187. data/test/acceptance/stubbing_error_backtrace_test.rb +0 -64
  188. data/test/acceptance/stubbing_frozen_object_test.rb +0 -88
  189. data/test/acceptance/stubbing_method_accepting_block_parameter_test.rb +0 -48
  190. data/test/acceptance/stubbing_method_unnecessarily_test.rb +0 -65
  191. data/test/acceptance/stubbing_nil_test.rb +0 -61
  192. data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +0 -143
  193. data/test/acceptance/stubbing_non_existent_class_method_test.rb +0 -157
  194. data/test/acceptance/stubbing_non_existent_instance_method_test.rb +0 -147
  195. data/test/acceptance/stubbing_non_public_any_instance_method_test.rb +0 -130
  196. data/test/acceptance/stubbing_non_public_class_method_test.rb +0 -163
  197. data/test/acceptance/stubbing_non_public_instance_method_test.rb +0 -143
  198. data/test/acceptance/stubbing_on_non_mock_object_test.rb +0 -64
  199. data/test/acceptance/stubbing_same_class_method_on_parent_and_child_classes_test.rb +0 -35
  200. data/test/acceptance/throw_test.rb +0 -45
  201. data/test/acceptance/unexpected_invocation_test.rb +0 -25
  202. data/test/acceptance/unstubbing_test.rb +0 -168
  203. data/test/assertions.rb +0 -8
  204. data/test/deprecation_disabler.rb +0 -15
  205. data/test/execution_point.rb +0 -36
  206. data/test/integration/mini_test_test.rb +0 -8
  207. data/test/integration/shared_tests.rb +0 -174
  208. data/test/integration/test_unit_test.rb +0 -8
  209. data/test/method_definer.rb +0 -24
  210. data/test/mini_test_result.rb +0 -90
  211. data/test/minitest_result.rb +0 -49
  212. data/test/simple_counter.rb +0 -13
  213. data/test/test_helper.rb +0 -50
  214. data/test/test_runner.rb +0 -58
  215. data/test/test_unit_result.rb +0 -20
  216. data/test/unit/any_instance_method_test.rb +0 -134
  217. data/test/unit/array_inspect_test.rb +0 -16
  218. data/test/unit/backtrace_filter_test.rb +0 -19
  219. data/test/unit/cardinality_test.rb +0 -56
  220. data/test/unit/central_test.rb +0 -100
  221. data/test/unit/change_state_side_effect_test.rb +0 -41
  222. data/test/unit/class_method_test.rb +0 -225
  223. data/test/unit/class_methods_test.rb +0 -40
  224. data/test/unit/configuration_test.rb +0 -38
  225. data/test/unit/date_time_inspect_test.rb +0 -21
  226. data/test/unit/exception_raiser_test.rb +0 -42
  227. data/test/unit/expectation_list_test.rb +0 -82
  228. data/test/unit/expectation_test.rb +0 -497
  229. data/test/unit/hash_inspect_test.rb +0 -16
  230. data/test/unit/hooks_test.rb +0 -29
  231. data/test/unit/in_state_ordering_constraint_test.rb +0 -43
  232. data/test/unit/method_matcher_test.rb +0 -28
  233. data/test/unit/mock_test.rb +0 -342
  234. data/test/unit/mockery_test.rb +0 -151
  235. data/test/unit/module_methods_test.rb +0 -19
  236. data/test/unit/multiple_yields_test.rb +0 -18
  237. data/test/unit/no_yields_test.rb +0 -18
  238. data/test/unit/object_inspect_test.rb +0 -39
  239. data/test/unit/object_methods_test.rb +0 -46
  240. data/test/unit/parameter_matchers/all_of_test.rb +0 -26
  241. data/test/unit/parameter_matchers/any_of_test.rb +0 -26
  242. data/test/unit/parameter_matchers/anything_test.rb +0 -21
  243. data/test/unit/parameter_matchers/equals_test.rb +0 -25
  244. data/test/unit/parameter_matchers/has_entries_test.rb +0 -51
  245. data/test/unit/parameter_matchers/has_entry_test.rb +0 -129
  246. data/test/unit/parameter_matchers/has_key_test.rb +0 -55
  247. data/test/unit/parameter_matchers/has_value_test.rb +0 -57
  248. data/test/unit/parameter_matchers/includes_test.rb +0 -102
  249. data/test/unit/parameter_matchers/instance_of_test.rb +0 -25
  250. data/test/unit/parameter_matchers/is_a_test.rb +0 -25
  251. data/test/unit/parameter_matchers/kind_of_test.rb +0 -25
  252. data/test/unit/parameter_matchers/not_test.rb +0 -26
  253. data/test/unit/parameter_matchers/regexp_matches_test.rb +0 -46
  254. data/test/unit/parameter_matchers/responds_with_test.rb +0 -32
  255. data/test/unit/parameter_matchers/stub_matcher.rb +0 -27
  256. data/test/unit/parameter_matchers/yaml_equivalent_test.rb +0 -25
  257. data/test/unit/parameters_matcher_test.rb +0 -121
  258. data/test/unit/receivers_test.rb +0 -66
  259. data/test/unit/return_values_test.rb +0 -63
  260. data/test/unit/sequence_test.rb +0 -104
  261. data/test/unit/single_return_value_test.rb +0 -14
  262. data/test/unit/single_yield_test.rb +0 -18
  263. data/test/unit/state_machine_test.rb +0 -98
  264. data/test/unit/string_inspect_test.rb +0 -11
  265. data/test/unit/thrower_test.rb +0 -20
  266. 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(mod)
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, &block)
32
- # @overload def mock(expected_methods_vs_return_values = {}, &block)
33
- # @overload def mock(name, expected_methods_vs_return_values = {}, &block)
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
- # @example Using the optional block to setup expectations & stubbed methods.
43
- # def test_motor_starts_and_stops
44
- # motor = mock('motor') do
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, &block) : Mockery.instance.unnamed_mock(&block)
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, &block)
68
- # @overload def stub(stubbed_methods_vs_return_values = {}, &block)
69
- # @overload def stub(name, stubbed_methods_vs_return_values = {}, &block)
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
- # @example Using the optional block to setup expectations & stubbed methods.
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, &block) : Mockery.instance.unnamed_mock(&block)
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, &block)
105
- # @overload def stub_everything(stubbed_methods_vs_return_values = {}, &block)
106
- # @overload def stub_everything(name, stubbed_methods_vs_return_values = {}, &block)
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, &block)
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, &block) : Mockery.instance.unnamed_mock(&block)
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') do
136
- # expects(:crack).in_sequence(breakfast)
137
- # expects(:fry).in_sequence(breakfast)
138
- # expects(:eat).in_sequence(breakfast)
139
- # end
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') do
163
- # expects(:switch_on).then(power.is('on'))
164
- # expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
165
- # expects(:adjust_volume).with(+5).when(power.is('on'))
166
- # expects(:select_channel).with('BBC World Service').when(power.is('on'))
167
- # expects(:adjust_volume).with(-5).when(power.is('on'))
168
- # expects(:switch_off).then(power.is('off'))
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(&block)
10
- if @argument.is_a?(Hash) then
7
+ def each
8
+ if @argument.is_a?(Hash)
11
9
  @argument.each do |method_name, return_value|
12
- block.call(method_name, return_value)
10
+ yield method_name, return_value
13
11
  end
14
12
  else
15
- block.call(@argument)
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
@@ -1,95 +1,106 @@
1
1
  module Mocha
2
-
3
2
  class Cardinality
4
-
5
3
  INFINITY = 1 / 0.0
6
4
 
7
- class << self
5
+ def initialize(required = 0, maximum = INFINITY)
6
+ update(required, maximum)
7
+ @invocations = []
8
+ end
8
9
 
9
- def exactly(count)
10
- new(count, count)
11
- end
10
+ def exactly(count)
11
+ update(count, count)
12
+ end
12
13
 
13
- def at_least(count)
14
- new(count, INFINITY)
15
- end
14
+ def at_least(count)
15
+ update(count, INFINITY)
16
+ end
16
17
 
17
- def at_most(count)
18
- new(0, count)
19
- end
18
+ def at_most(count)
19
+ update(0, count)
20
+ end
20
21
 
21
- def times(range_or_count)
22
- case range_or_count
23
- when Range then new(range_or_count.first, range_or_count.last)
24
- else new(range_or_count, range_or_count)
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 initialize(required, maximum)
31
- @required, @maximum = required, maximum
29
+ def <<(invocation)
30
+ @invocations << invocation
32
31
  end
33
32
 
34
- def invocations_allowed?(invocation_count)
35
- invocation_count < maximum
33
+ def invocations_allowed?
34
+ @invocations.size < maximum
36
35
  end
37
36
 
38
- def satisfied?(invocations_so_far)
39
- invocations_so_far >= required
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?(invocation_count)
47
- (invocation_count >= required) && (invocation_count <= maximum)
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 == 0 && infinite?(maximum)
50
+ required.zero? && infinite?(maximum)
52
51
  end
53
52
 
54
- def used?(invocation_count)
55
- (invocation_count > 0) || (maximum == 0)
53
+ def used?
54
+ @invocations.any? || maximum.zero?
56
55
  end
57
56
 
58
- def mocha_inspect
57
+ # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
58
+ def anticipated_times
59
59
  if allowed_any_number_of_times?
60
- "allowed any number of times"
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
- if required == 0 && maximum == 0
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 times(number)
87
+ def count(number)
81
88
  case number
82
- when 0 then "no times"
83
- when 1 then "once"
84
- when 2 then "twice"
85
- else "#{number} times"
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
- unless stubba_methods.detect { |m| m.matches?(method) }
13
- method.stub
14
- stubba_methods.push(method)
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
- if existing = stubba_methods.detect { |m| m.matches?(method) }
20
- existing.unstub
21
- stubba_methods.delete(existing)
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? do
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
@@ -1,7 +1,5 @@
1
1
  module Mocha
2
-
3
2
  class ChangeStateSideEffect
4
-
5
3
  def initialize(state)
6
4
  @state = state
7
5
  end
@@ -13,7 +11,5 @@ module Mocha
13
11
  def mocha_inspect
14
12
  "then #{@state.mocha_inspect}"
15
13
  end
16
-
17
14
  end
18
-
19
15
  end
@@ -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
- @mocha ||= Mocha::Mockery.instance.mock_impersonating_any_instance_of(@stubba_object)
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 stubba_object
25
+ def stubba_class
31
26
  @stubba_object
32
27
  end
33
28
 
34
- def method_exists?(method, include_public_methods = true)
35
- if include_public_methods
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