mocha 1.1.0 → 1.13.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 (263) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +1 -0
  3. data/.rubocop.yml +61 -0
  4. data/.rubocop_todo.yml +27 -0
  5. data/.yardopts +1 -0
  6. data/CONTRIBUTING.md +4 -9
  7. data/README.md +114 -28
  8. data/RELEASE.md +248 -1
  9. data/Rakefile +53 -35
  10. data/gemfiles/Gemfile.test-unit.latest +5 -1
  11. data/init.rb +1 -3
  12. data/lib/mocha/any_instance_method.rb +12 -72
  13. data/lib/mocha/api.rb +121 -56
  14. data/lib/mocha/argument_iterator.rb +4 -8
  15. data/lib/mocha/backtrace_filter.rb +1 -5
  16. data/lib/mocha/block_matcher.rb +31 -0
  17. data/lib/mocha/cardinality.rb +60 -49
  18. data/lib/mocha/central.rb +21 -12
  19. data/lib/mocha/change_state_side_effect.rb +0 -4
  20. data/lib/mocha/class_methods.rb +19 -20
  21. data/lib/mocha/configuration.rb +361 -18
  22. data/lib/mocha/debug.rb +3 -2
  23. data/lib/mocha/deprecation.rb +8 -11
  24. data/lib/mocha/detection/mini_test.rb +0 -2
  25. data/lib/mocha/detection/test_unit.rb +3 -5
  26. data/lib/mocha/error_with_filtered_backtrace.rb +13 -0
  27. data/lib/mocha/exception_raiser.rb +4 -6
  28. data/lib/mocha/expectation.rb +125 -89
  29. data/lib/mocha/expectation_error.rb +1 -1
  30. data/lib/mocha/expectation_error_factory.rb +0 -1
  31. data/lib/mocha/expectation_list.rb +7 -11
  32. data/lib/mocha/hooks.rb +1 -3
  33. data/lib/mocha/in_state_ordering_constraint.rb +0 -4
  34. data/lib/mocha/inspect.rb +30 -38
  35. data/lib/mocha/instance_method.rb +15 -8
  36. data/lib/mocha/integration/mini_test/adapter.rb +2 -4
  37. data/lib/mocha/integration/mini_test/exception_translation.rb +1 -1
  38. data/lib/mocha/integration/mini_test/nothing.rb +4 -4
  39. data/lib/mocha/integration/mini_test/version_13.rb +4 -1
  40. data/lib/mocha/integration/mini_test/version_140.rb +4 -1
  41. data/lib/mocha/integration/mini_test/version_141.rb +4 -1
  42. data/lib/mocha/integration/mini_test/version_142_to_172.rb +4 -1
  43. data/lib/mocha/integration/mini_test/version_200.rb +4 -1
  44. data/lib/mocha/integration/mini_test/version_201_to_222.rb +4 -1
  45. data/lib/mocha/integration/mini_test/version_2110_to_2111.rb +4 -1
  46. data/lib/mocha/integration/mini_test/version_2112_to_320.rb +4 -1
  47. data/lib/mocha/integration/mini_test/version_230_to_2101.rb +4 -1
  48. data/lib/mocha/integration/mini_test.rb +7 -0
  49. data/lib/mocha/integration/monkey_patcher.rb +8 -2
  50. data/lib/mocha/integration/test_unit/adapter.rb +5 -6
  51. data/lib/mocha/integration/test_unit/gem_version_200.rb +5 -2
  52. data/lib/mocha/integration/test_unit/gem_version_201_to_202.rb +5 -2
  53. data/lib/mocha/integration/test_unit/gem_version_203_to_220.rb +5 -2
  54. data/lib/mocha/integration/test_unit/gem_version_230_to_250.rb +5 -2
  55. data/lib/mocha/integration/test_unit/nothing.rb +4 -4
  56. data/lib/mocha/integration/test_unit/ruby_version_185_and_below.rb +4 -1
  57. data/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb +4 -1
  58. data/lib/mocha/integration/test_unit.rb +7 -0
  59. data/lib/mocha/integration.rb +2 -5
  60. data/lib/mocha/invocation.rb +77 -0
  61. data/lib/mocha/is_a.rb +0 -2
  62. data/lib/mocha/logger.rb +0 -4
  63. data/lib/mocha/macos_version.rb +5 -0
  64. data/lib/mocha/method_matcher.rb +1 -5
  65. data/lib/mocha/minitest.rb +8 -0
  66. data/lib/mocha/mock.rb +94 -46
  67. data/lib/mocha/mockery.rb +72 -98
  68. data/lib/mocha/names.rb +2 -12
  69. data/lib/mocha/not_initialized_error.rb +7 -0
  70. data/lib/mocha/object_methods.rb +25 -31
  71. data/lib/mocha/parameter_matchers/all_of.rb +2 -8
  72. data/lib/mocha/parameter_matchers/any_of.rb +2 -8
  73. data/lib/mocha/parameter_matchers/any_parameters.rb +3 -9
  74. data/lib/mocha/parameter_matchers/anything.rb +2 -8
  75. data/lib/mocha/parameter_matchers/base.rb +6 -12
  76. data/lib/mocha/parameter_matchers/equals.rb +1 -7
  77. data/lib/mocha/parameter_matchers/{query_string.rb → equivalent_uri.rb} +15 -15
  78. data/lib/mocha/parameter_matchers/has_entries.rb +2 -7
  79. data/lib/mocha/parameter_matchers/has_entry.rb +26 -21
  80. data/lib/mocha/parameter_matchers/has_key.rb +2 -7
  81. data/lib/mocha/parameter_matchers/has_keys.rb +53 -0
  82. data/lib/mocha/parameter_matchers/has_value.rb +2 -7
  83. data/lib/mocha/parameter_matchers/includes.rb +50 -8
  84. data/lib/mocha/parameter_matchers/instance_methods.rb +18 -0
  85. data/lib/mocha/parameter_matchers/instance_of.rb +0 -6
  86. data/lib/mocha/parameter_matchers/is_a.rb +2 -7
  87. data/lib/mocha/parameter_matchers/kind_of.rb +2 -6
  88. data/lib/mocha/parameter_matchers/not.rb +2 -7
  89. data/lib/mocha/parameter_matchers/optionally.rb +4 -10
  90. data/lib/mocha/parameter_matchers/regexp_matches.rb +0 -6
  91. data/lib/mocha/parameter_matchers/responds_with.rb +3 -8
  92. data/lib/mocha/parameter_matchers/yaml_equivalent.rb +2 -6
  93. data/lib/mocha/parameter_matchers.rb +3 -4
  94. data/lib/mocha/parameters_matcher.rb +6 -9
  95. data/lib/mocha/raised_exception.rb +11 -0
  96. data/lib/mocha/receivers.rb +10 -14
  97. data/lib/mocha/return_values.rb +4 -8
  98. data/lib/mocha/ruby_version.rb +4 -0
  99. data/lib/mocha/sequence.rb +4 -9
  100. data/lib/mocha/setup.rb +5 -0
  101. data/lib/mocha/single_return_value.rb +2 -5
  102. data/lib/mocha/singleton_class.rb +9 -0
  103. data/lib/mocha/state_machine.rb +33 -46
  104. data/lib/mocha/stubbed_method.rb +125 -0
  105. data/lib/mocha/stubbing_error.rb +2 -13
  106. data/lib/mocha/test_unit.rb +7 -2
  107. data/lib/mocha/thrower.rb +4 -6
  108. data/lib/mocha/thrown_object.rb +12 -0
  109. data/lib/mocha/version.rb +1 -1
  110. data/lib/mocha/yield_parameters.rb +7 -17
  111. data/lib/mocha.rb +8 -0
  112. data/mocha.gemspec +42 -40
  113. data/yard-templates/default/layout/html/google_analytics.erb +6 -9
  114. data/yard-templates/default/layout/html/setup.rb +2 -3
  115. metadata +45 -191
  116. data/bin/build-matrix +0 -71
  117. data/gemfiles/Gemfile.minitest.1.3.0 +0 -7
  118. data/gemfiles/Gemfile.minitest.1.4.0 +0 -7
  119. data/gemfiles/Gemfile.minitest.1.4.1 +0 -7
  120. data/gemfiles/Gemfile.minitest.1.4.2 +0 -7
  121. data/gemfiles/Gemfile.minitest.2.0.0 +0 -7
  122. data/gemfiles/Gemfile.minitest.2.0.1 +0 -7
  123. data/gemfiles/Gemfile.minitest.2.11.0 +0 -7
  124. data/gemfiles/Gemfile.minitest.2.11.2 +0 -7
  125. data/gemfiles/Gemfile.minitest.2.3.0 +0 -7
  126. data/gemfiles/Gemfile.test-unit.2.0.0 +0 -7
  127. data/gemfiles/Gemfile.test-unit.2.0.1 +0 -7
  128. data/gemfiles/Gemfile.test-unit.2.0.3 +0 -7
  129. data/lib/mocha/class_method.rb +0 -127
  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/single_yield.rb +0 -18
  138. data/lib/mocha/standalone.rb +0 -4
  139. data/lib/mocha/unexpected_invocation.rb +0 -26
  140. data/lib/mocha_standalone.rb +0 -4
  141. data/test/acceptance/acceptance_test_helper.rb +0 -41
  142. data/test/acceptance/bug_18914_test.rb +0 -43
  143. data/test/acceptance/bug_21465_test.rb +0 -34
  144. data/test/acceptance/bug_21563_test.rb +0 -25
  145. data/test/acceptance/exception_rescue_test.rb +0 -55
  146. data/test/acceptance/expectations_on_multiple_methods_test.rb +0 -55
  147. data/test/acceptance/expected_invocation_count_test.rb +0 -232
  148. data/test/acceptance/failure_messages_test.rb +0 -64
  149. data/test/acceptance/issue_65_test.rb +0 -63
  150. data/test/acceptance/issue_70_test.rb +0 -55
  151. data/test/acceptance/mocha_example_test.rb +0 -98
  152. data/test/acceptance/mocha_test_result_test.rb +0 -84
  153. data/test/acceptance/mock_test.rb +0 -100
  154. data/test/acceptance/mock_with_initializer_block_test.rb +0 -51
  155. data/test/acceptance/mocked_methods_dispatch_test.rb +0 -78
  156. data/test/acceptance/multiple_expectations_failure_message_test.rb +0 -68
  157. data/test/acceptance/optional_parameters_test.rb +0 -70
  158. data/test/acceptance/parameter_matcher_test.rb +0 -337
  159. data/test/acceptance/partial_mocks_test.rb +0 -47
  160. data/test/acceptance/prepend_test.rb +0 -88
  161. data/test/acceptance/raise_exception_test.rb +0 -39
  162. data/test/acceptance/return_value_test.rb +0 -52
  163. data/test/acceptance/sequence_test.rb +0 -192
  164. data/test/acceptance/states_test.rb +0 -70
  165. data/test/acceptance/stub_any_instance_method_defined_on_superclass_test.rb +0 -34
  166. data/test/acceptance/stub_any_instance_method_test.rb +0 -238
  167. data/test/acceptance/stub_class_method_defined_on_active_record_association_proxy_test.rb +0 -106
  168. data/test/acceptance/stub_class_method_defined_on_class_test.rb +0 -78
  169. data/test/acceptance/stub_class_method_defined_on_module_test.rb +0 -75
  170. data/test/acceptance/stub_class_method_defined_on_superclass_test.rb +0 -112
  171. data/test/acceptance/stub_everything_test.rb +0 -56
  172. data/test/acceptance/stub_instance_method_defined_on_active_record_association_proxy_test.rb +0 -93
  173. data/test/acceptance/stub_instance_method_defined_on_class_and_aliased_test.rb +0 -69
  174. data/test/acceptance/stub_instance_method_defined_on_class_test.rb +0 -69
  175. data/test/acceptance/stub_instance_method_defined_on_kernel_module_test.rb +0 -75
  176. data/test/acceptance/stub_instance_method_defined_on_module_test.rb +0 -75
  177. data/test/acceptance/stub_instance_method_defined_on_object_class_test.rb +0 -75
  178. data/test/acceptance/stub_instance_method_defined_on_singleton_class_test.rb +0 -70
  179. data/test/acceptance/stub_instance_method_defined_on_superclass_test.rb +0 -72
  180. data/test/acceptance/stub_module_method_test.rb +0 -163
  181. data/test/acceptance/stub_test.rb +0 -52
  182. data/test/acceptance/stubba_example_test.rb +0 -102
  183. data/test/acceptance/stubba_test_result_test.rb +0 -66
  184. data/test/acceptance/stubbing_error_backtrace_test.rb +0 -64
  185. data/test/acceptance/stubbing_frozen_object_test.rb +0 -88
  186. data/test/acceptance/stubbing_method_accepting_block_parameter_test.rb +0 -48
  187. data/test/acceptance/stubbing_method_unnecessarily_test.rb +0 -65
  188. data/test/acceptance/stubbing_nil_test.rb +0 -59
  189. data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +0 -130
  190. data/test/acceptance/stubbing_non_existent_class_method_test.rb +0 -157
  191. data/test/acceptance/stubbing_non_existent_instance_method_test.rb +0 -147
  192. data/test/acceptance/stubbing_non_public_any_instance_method_test.rb +0 -130
  193. data/test/acceptance/stubbing_non_public_class_method_test.rb +0 -163
  194. data/test/acceptance/stubbing_non_public_instance_method_test.rb +0 -143
  195. data/test/acceptance/stubbing_on_non_mock_object_test.rb +0 -64
  196. data/test/acceptance/stubbing_same_class_method_on_parent_and_child_classes_test.rb +0 -35
  197. data/test/acceptance/throw_test.rb +0 -45
  198. data/test/acceptance/unexpected_invocation_test.rb +0 -25
  199. data/test/acceptance/unstubbing_test.rb +0 -168
  200. data/test/assertions.rb +0 -6
  201. data/test/deprecation_disabler.rb +0 -15
  202. data/test/execution_point.rb +0 -36
  203. data/test/integration/mini_test_test.rb +0 -8
  204. data/test/integration/shared_tests.rb +0 -174
  205. data/test/integration/test_unit_test.rb +0 -8
  206. data/test/method_definer.rb +0 -24
  207. data/test/mini_test_result.rb +0 -90
  208. data/test/minitest_result.rb +0 -49
  209. data/test/simple_counter.rb +0 -13
  210. data/test/test_helper.rb +0 -50
  211. data/test/test_runner.rb +0 -58
  212. data/test/test_unit_result.rb +0 -20
  213. data/test/unit/any_instance_method_test.rb +0 -132
  214. data/test/unit/array_inspect_test.rb +0 -16
  215. data/test/unit/backtrace_filter_test.rb +0 -19
  216. data/test/unit/cardinality_test.rb +0 -56
  217. data/test/unit/central_test.rb +0 -100
  218. data/test/unit/change_state_side_effect_test.rb +0 -41
  219. data/test/unit/class_method_test.rb +0 -223
  220. data/test/unit/class_methods_test.rb +0 -40
  221. data/test/unit/configuration_test.rb +0 -38
  222. data/test/unit/date_time_inspect_test.rb +0 -21
  223. data/test/unit/exception_raiser_test.rb +0 -42
  224. data/test/unit/expectation_list_test.rb +0 -82
  225. data/test/unit/expectation_test.rb +0 -497
  226. data/test/unit/hash_inspect_test.rb +0 -16
  227. data/test/unit/hooks_test.rb +0 -29
  228. data/test/unit/in_state_ordering_constraint_test.rb +0 -43
  229. data/test/unit/method_matcher_test.rb +0 -28
  230. data/test/unit/mock_test.rb +0 -341
  231. data/test/unit/mockery_test.rb +0 -151
  232. data/test/unit/module_methods_test.rb +0 -19
  233. data/test/unit/multiple_yields_test.rb +0 -18
  234. data/test/unit/no_yields_test.rb +0 -18
  235. data/test/unit/object_inspect_test.rb +0 -38
  236. data/test/unit/object_methods_test.rb +0 -46
  237. data/test/unit/parameter_matchers/all_of_test.rb +0 -26
  238. data/test/unit/parameter_matchers/any_of_test.rb +0 -26
  239. data/test/unit/parameter_matchers/anything_test.rb +0 -21
  240. data/test/unit/parameter_matchers/equals_test.rb +0 -25
  241. data/test/unit/parameter_matchers/has_entries_test.rb +0 -51
  242. data/test/unit/parameter_matchers/has_entry_test.rb +0 -129
  243. data/test/unit/parameter_matchers/has_key_test.rb +0 -55
  244. data/test/unit/parameter_matchers/has_value_test.rb +0 -57
  245. data/test/unit/parameter_matchers/includes_test.rb +0 -59
  246. data/test/unit/parameter_matchers/instance_of_test.rb +0 -25
  247. data/test/unit/parameter_matchers/is_a_test.rb +0 -25
  248. data/test/unit/parameter_matchers/kind_of_test.rb +0 -25
  249. data/test/unit/parameter_matchers/not_test.rb +0 -26
  250. data/test/unit/parameter_matchers/regexp_matches_test.rb +0 -46
  251. data/test/unit/parameter_matchers/responds_with_test.rb +0 -32
  252. data/test/unit/parameter_matchers/stub_matcher.rb +0 -27
  253. data/test/unit/parameter_matchers/yaml_equivalent_test.rb +0 -25
  254. data/test/unit/parameters_matcher_test.rb +0 -121
  255. data/test/unit/receivers_test.rb +0 -66
  256. data/test/unit/return_values_test.rb +0 -63
  257. data/test/unit/sequence_test.rb +0 -104
  258. data/test/unit/single_return_value_test.rb +0 -14
  259. data/test/unit/single_yield_test.rb +0 -18
  260. data/test/unit/state_machine_test.rb +0 -98
  261. data/test/unit/string_inspect_test.rb +0 -11
  262. data/test/unit/thrower_test.rb +0 -20
  263. data/test/unit/yield_parameters_test.rb +0 -93
@@ -9,12 +9,12 @@ require 'mocha/is_a'
9
9
  require 'mocha/in_state_ordering_constraint'
10
10
  require 'mocha/change_state_side_effect'
11
11
  require 'mocha/cardinality'
12
+ require 'mocha/configuration'
13
+ require 'mocha/block_matcher'
12
14
 
13
15
  module Mocha
14
-
15
16
  # Methods on expectations returned from {Mock#expects}, {Mock#stubs}, {ObjectMethods#expects} and {ObjectMethods#stubs}.
16
17
  class Expectation
17
-
18
18
  # Modifies expectation so that the number of calls to the expected method must be within a specific +range+.
19
19
  #
20
20
  # @param [Range,Integer] range specifies the allowable range in the number of expected invocations.
@@ -42,7 +42,7 @@ module Mocha
42
42
  # object.expected_method
43
43
  # # => verify fails
44
44
  def times(range)
45
- @cardinality = Cardinality.times(range)
45
+ @cardinality.times(range)
46
46
  self
47
47
  end
48
48
 
@@ -68,7 +68,7 @@ module Mocha
68
68
  # object.expected_method
69
69
  # # => verify fails
70
70
  def twice
71
- @cardinality = Cardinality.exactly(2)
71
+ @cardinality.exactly(2)
72
72
  self
73
73
  end
74
74
 
@@ -93,7 +93,7 @@ module Mocha
93
93
  # object.expects(:expected_method).once
94
94
  # # => verify fails
95
95
  def once
96
- @cardinality = Cardinality.exactly(1)
96
+ @cardinality.exactly(1)
97
97
  self
98
98
  end
99
99
 
@@ -110,7 +110,7 @@ module Mocha
110
110
  # object.expects(:expected_method).never
111
111
  # # => verify succeeds
112
112
  def never
113
- @cardinality = Cardinality.exactly(0)
113
+ @cardinality.exactly(0)
114
114
  self
115
115
  end
116
116
 
@@ -130,7 +130,7 @@ module Mocha
130
130
  # object.expected_method
131
131
  # # => verify fails
132
132
  def at_least(minimum_number_of_times)
133
- @cardinality = Cardinality.at_least(minimum_number_of_times)
133
+ @cardinality.at_least(minimum_number_of_times)
134
134
  self
135
135
  end
136
136
 
@@ -149,7 +149,6 @@ module Mocha
149
149
  # # => verify fails
150
150
  def at_least_once
151
151
  at_least(1)
152
- self
153
152
  end
154
153
 
155
154
  # Modifies expectation so that the expected method must be called at most a +maximum_number_of_times+.
@@ -167,7 +166,7 @@ module Mocha
167
166
  # object.expects(:expected_method).at_most(2)
168
167
  # 3.times { object.expected_method } # => unexpected invocation
169
168
  def at_most(maximum_number_of_times)
170
- @cardinality = Cardinality.at_most(maximum_number_of_times)
169
+ @cardinality.at_most(maximum_number_of_times)
171
170
  self
172
171
  end
173
172
 
@@ -184,9 +183,8 @@ module Mocha
184
183
  # object = mock()
185
184
  # object.expects(:expected_method).at_most_once
186
185
  # 2.times { object.expected_method } # => unexpected invocation
187
- def at_most_once()
186
+ def at_most_once
188
187
  at_most(1)
189
- self
190
188
  end
191
189
 
192
190
  # Modifies expectation so that the expected method must be called with +expected_parameters+.
@@ -225,7 +223,49 @@ module Mocha
225
223
  self
226
224
  end
227
225
 
228
- # Modifies expectation so that when the expected method is called, it yields with the specified +parameters+.
226
+ # Modifies expectation so that the expected method must be called with a block.
227
+ #
228
+ # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
229
+ #
230
+ # @example Expected method must be called with a block.
231
+ # object = mock()
232
+ # object.expects(:expected_method).with_block_given
233
+ # object.expected_method { 1 + 1 }
234
+ # # => verify succeeds
235
+ #
236
+ # object = mock()
237
+ # object.expects(:expected_method).with_block_given
238
+ # object.expected_method
239
+ # # => verify fails
240
+ def with_block_given
241
+ @block_matcher = BlockMatchers::BlockGiven.new
242
+ self
243
+ end
244
+
245
+ # Modifies expectation so that the expected method must be called without a block.
246
+ #
247
+ # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
248
+ #
249
+ # @example Expected method must be called without a block.
250
+ # object = mock()
251
+ # object.expects(:expected_method).with_no_block_given
252
+ # object.expected_method
253
+ # # => verify succeeds
254
+ #
255
+ # object = mock()
256
+ # object.expects(:expected_method).with_block_given
257
+ # object.expected_method { 1 + 1 }
258
+ # # => verify fails
259
+ def with_no_block_given
260
+ @block_matcher = BlockMatchers::NoBlockGiven.new
261
+ self
262
+ end
263
+
264
+ # Modifies expectation so that when the expected method is called, it yields to the block with the specified +parameters+.
265
+ #
266
+ # If no +parameters+ are specified, it yields to the block without any parameters.
267
+ #
268
+ # If no block is provided, the method will still attempt to yield resulting in a +LocalJumpError+. Note that this is what would happen if a "real" (non-mock) method implementation tried to yield to a non-existent block.
229
269
  #
230
270
  # May be called multiple times on the same expectation for consecutive invocations.
231
271
  #
@@ -233,51 +273,58 @@ module Mocha
233
273
  # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
234
274
  # @see #then
235
275
  #
276
+ # @example Yield when expected method is invoked.
277
+ # benchmark = mock()
278
+ # benchmark.expects(:measure).yields
279
+ # yielded = false
280
+ # benchmark.measure { yielded = true }
281
+ # yielded # => true
282
+ #
236
283
  # @example Yield parameters when expected method is invoked.
237
- # object = mock()
238
- # object.expects(:expected_method).yields('result')
239
- # yielded_value = nil
240
- # object.expected_method { |value| yielded_value = value }
241
- # yielded_value # => 'result'
284
+ # fibonacci = mock()
285
+ # fibonacci.expects(:next_pair).yields(0, 1)
286
+ # sum = 0
287
+ # fibonacci.next_pair { |first, second| sum = first + second }
288
+ # sum # => 1
242
289
  #
243
290
  # @example Yield different parameters on different invocations of the expected method.
244
- # object = mock()
245
- # object.stubs(:expected_method).yields(1).then.yields(2)
246
- # yielded_values_from_first_invocation = []
247
- # yielded_values_from_second_invocation = []
248
- # object.expected_method { |value| yielded_values_from_first_invocation << value } # first invocation
249
- # object.expected_method { |value| yielded_values_from_second_invocation << value } # second invocation
250
- # yielded_values_from_first_invocation # => [1]
251
- # yielded_values_from_second_invocation # => [2]
291
+ # fibonacci = mock()
292
+ # fibonacci.expects(:next_pair).yields(0, 1).then.yields(1, 1)
293
+ # sum = 0
294
+ # fibonacci.next_pair { |first, second| sum = first + second }
295
+ # sum # => 1
296
+ # fibonacci.next_pair { |first, second| sum = first + second }
297
+ # sum # => 2
252
298
  def yields(*parameters)
253
- @yield_parameters.add(*parameters)
254
- self
299
+ multiple_yields(parameters)
255
300
  end
256
301
 
257
302
  # Modifies expectation so that when the expected method is called, it yields multiple times per invocation with the specified +parameter_groups+.
258
303
  #
259
- # @param [*Array<Array>] parameter_groups each element of +parameter_groups+ should iself be an +Array+ representing the parameters to be passed to the block for a single yield.
304
+ # If no block is provided, the method will still attempt to yield resulting in a +LocalJumpError+. Note that this is what would happen if a "real" (non-mock) method implementation tried to yield to a non-existent block.
305
+ #
306
+ # @param [*Array<Array>] parameter_groups each element of +parameter_groups+ should iself be an +Array+ representing the parameters to be passed to the block for a single yield. Any element of +parameter_groups+ that is not an +Array+ is wrapped in an +Array+.
260
307
  # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
261
308
  # @see #then
262
309
  #
263
- # @example When the +expected_method+ is called, the stub will invoke the block twice, the first time it passes +'result_1'+, +'result_2'+ as the parameters, and the second time it passes 'result_3' as the parameters.
264
- # object = mock()
265
- # object.expects(:expected_method).multiple_yields(['result_1', 'result_2'], ['result_3'])
266
- # yielded_values = []
267
- # object.expected_method { |*values| yielded_values << values }
268
- # yielded_values # => [['result_1', 'result_2'], ['result_3]]
269
- #
270
- # @example Yield different groups of parameters on different invocations of the expected method.
271
- # object = mock()
272
- # object.stubs(:expected_method).multiple_yields([1, 2], [3]).then.multiple_yields([4], [5, 6])
273
- # yielded_values_from_first_invocation = []
274
- # yielded_values_from_second_invocation = []
275
- # object.expected_method { |*values| yielded_values_from_first_invocation << values } # first invocation
276
- # object.expected_method { |*values| yielded_values_from_second_invocation << values } # second invocation
277
- # yielded_values_from_first_invocation # => [[1, 2], [3]]
278
- # yielded_values_from_second_invocation # => [[4], [5, 6]]
310
+ # @example When +foreach+ is called, the stub will invoke the block twice, the first time it passes ['row1_col1', 'row1_col2'] as the parameters, and the second time it passes ['row2_col1', ''] as the parameters.
311
+ # csv = mock()
312
+ # csv.expects(:foreach).with("path/to/file.csv").multiple_yields(['row1_col1', 'row1_col2'], ['row2_col1', ''])
313
+ # rows = []
314
+ # csv.foreach { |row| rows << row }
315
+ # rows # => [['row1_col1', 'row1_col2'], ['row2_col1', '']]
316
+ #
317
+ # @example Yield different groups of parameters on different invocations of the expected method. Simulating a situation where the CSV file at 'path/to/file.csv' has been modified between the two calls to +foreach+.
318
+ # csv = mock()
319
+ # csv.stubs(:foreach).with("path/to/file.csv").multiple_yields(['old_row1_col1', 'old_row1_col2'], ['old_row2_col1', '']).then.multiple_yields(['new_row1_col1', ''], ['new_row2_col1', 'new_row2_col2'])
320
+ # rows_from_first_invocation = []
321
+ # rows_from_second_invocation = []
322
+ # csv.foreach { |row| rows_from_first_invocation << row } # first invocation
323
+ # csv.foreach { |row| rows_from_second_invocation << row } # second invocation
324
+ # rows_from_first_invocation # => [['old_row1_col1', 'old_row1_col2'], ['old_row2_col1', '']]
325
+ # rows_from_second_invocation # => [['new_row1_col1', ''], ['new_row2_col1', 'new_row2_col2']]
279
326
  def multiple_yields(*parameter_groups)
280
- @yield_parameters.multiple_add(*parameter_groups)
327
+ @yield_parameters.add(*parameter_groups)
281
328
  self
282
329
  end
283
330
 
@@ -409,9 +456,9 @@ module Mocha
409
456
 
410
457
  # @overload def then
411
458
  # Used as syntactic sugar to improve readability. It has no effect on state of the expectation.
412
- # @overload def then(state_machine.is(state_name))
413
- # Used to change the +state_machine+ to the state specified by +state_name+ when the expected invocation occurs.
414
- # @param [StateMachine::State] state_machine.is(state_name) provides a mechanism to change the +state_machine+ into the state specified by +state_name+ when the expected method is invoked.
459
+ # @overload def then(state)
460
+ # Used to change the +state_machine+ to the specified state when the expected invocation occurs.
461
+ # @param [StateMachine::State] state state_machine.is(state_name) provides a mechanism to change the +state_machine+ into the state specified by +state_name+ when the expected method is invoked.
415
462
  #
416
463
  # @see API#states
417
464
  # @see StateMachine
@@ -437,17 +484,14 @@ module Mocha
437
484
  # radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
438
485
  # radio.expects(:adjust_volume).with(-5).when(power.is('on'))
439
486
  # radio.expects(:switch_off).then(power.is('off'))
440
- def then(*parameters)
441
- if parameters.length == 1
442
- state = parameters.first
443
- add_side_effect(ChangeStateSideEffect.new(state))
444
- end
487
+ def then(state = nil)
488
+ add_side_effect(ChangeStateSideEffect.new(state)) if state
445
489
  self
446
490
  end
447
491
 
448
- # Constrains the expectation to occur only when the +state_machine+ is in the state specified by +state_name+.
492
+ # Constrains the expectation to occur only when the +state_machine+ is in the state specified by +state_predicate+.
449
493
  #
450
- # @param [StateMachine::StatePredicate] state_machine.is(state_name) provides a mechanism to determine whether the +state_machine+ is in the state specified by +state_name+ when the expected method is invoked.
494
+ # @param [StateMachine::StatePredicate] state_predicate +state_machine.is(state_name)+ provides a mechanism to determine whether the +state_machine+ is in the state specified by +state_predicate+ when the expected method is invoked.
451
495
  # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
452
496
  #
453
497
  # @see API#states
@@ -479,7 +523,8 @@ module Mocha
479
523
  #
480
524
  # An expected method can appear in multiple sequences.
481
525
  #
482
- # @param [*Array<Sequence>] sequences sequences in which expected method should appear.
526
+ # @param [Sequence] sequence sequence in which expected method should appear.
527
+ # @param [*Array<Sequence>] sequences more sequences in which expected method should appear.
483
528
  # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
484
529
  #
485
530
  # @see API#sequence
@@ -491,8 +536,8 @@ module Mocha
491
536
  # egg.expects(:crack).in_sequence(breakfast)
492
537
  # egg.expects(:fry).in_sequence(breakfast)
493
538
  # egg.expects(:eat).in_sequence(breakfast)
494
- def in_sequence(*sequences)
495
- sequences.each { |sequence| add_in_sequence_ordering_constraint(sequence) }
539
+ def in_sequence(sequence, *sequences)
540
+ sequences.unshift(sequence).each { |seq| add_in_sequence_ordering_constraint(seq) }
496
541
  self
497
542
  end
498
543
 
@@ -504,9 +549,10 @@ module Mocha
504
549
  @mock = mock
505
550
  @method_matcher = MethodMatcher.new(expected_method_name.to_sym)
506
551
  @parameters_matcher = ParametersMatcher.new
552
+ @block_matcher = BlockMatchers::OptionalBlock.new
507
553
  @ordering_constraints = []
508
554
  @side_effects = []
509
- @cardinality, @invocation_count = Cardinality.exactly(1), 0
555
+ @cardinality = Cardinality.new.exactly(1)
510
556
  @return_values = ReturnValues.new
511
557
  @yield_parameters = YieldParameters.new
512
558
  @backtrace = backtrace || caller
@@ -529,12 +575,12 @@ module Mocha
529
575
 
530
576
  # @private
531
577
  def perform_side_effects
532
- @side_effects.each { |side_effect| side_effect.perform }
578
+ @side_effects.each(&:perform)
533
579
  end
534
580
 
535
581
  # @private
536
582
  def in_correct_order?
537
- @ordering_constraints.all? { |ordering_constraint| ordering_constraint.allows_invocation_now? }
583
+ @ordering_constraints.all?(&:allows_invocation_now?)
538
584
  end
539
585
 
540
586
  # @private
@@ -543,70 +589,60 @@ module Mocha
543
589
  end
544
590
 
545
591
  # @private
546
- def match?(actual_method_name, *actual_parameters)
547
- @method_matcher.match?(actual_method_name) && @parameters_matcher.match?(actual_parameters) && in_correct_order?
592
+ def match?(invocation)
593
+ @method_matcher.match?(invocation.method_name) && @parameters_matcher.match?(invocation.arguments) && @block_matcher.match?(invocation.block) && in_correct_order?
548
594
  end
549
595
 
550
596
  # @private
551
597
  def invocations_allowed?
552
- @cardinality.invocations_allowed?(@invocation_count)
598
+ @cardinality.invocations_allowed?
553
599
  end
554
600
 
555
601
  # @private
556
602
  def satisfied?
557
- @cardinality.satisfied?(@invocation_count)
603
+ @cardinality.satisfied?
558
604
  end
559
605
 
560
606
  # @private
561
- def invoke
562
- @invocation_count += 1
563
- perform_side_effects()
564
- if block_given? then
565
- @yield_parameters.next_invocation.each do |yield_parameters|
566
- yield(*yield_parameters)
567
- end
568
- end
569
- @return_values.next
607
+ def invoke(invocation)
608
+ perform_side_effects
609
+ @cardinality << invocation
610
+ invocation.call(@yield_parameters, @return_values)
570
611
  end
571
612
 
572
613
  # @private
573
614
  def verified?(assertion_counter = nil)
574
615
  assertion_counter.increment if assertion_counter && @cardinality.needs_verifying?
575
- @cardinality.verified?(@invocation_count)
616
+ @cardinality.verified?
576
617
  end
577
618
 
578
619
  # @private
579
620
  def used?
580
- @cardinality.used?(@invocation_count)
621
+ @cardinality.used?
581
622
  end
582
623
 
583
624
  # @private
584
625
  def inspect
585
626
  address = __id__ * 2
586
627
  address += 0x100000000 if address < 0
587
- "#<Expectation:0x#{'%x' % address} #{mocha_inspect} >"
628
+ "#<Expectation:0x#{format('%x', address)} #{mocha_inspect} >"
588
629
  end
589
630
 
590
631
  # @private
591
632
  def mocha_inspect
592
- message = "#{@cardinality.mocha_inspect}, "
593
- message << case @invocation_count
594
- when 0 then "not yet invoked"
595
- when 1 then "invoked once"
596
- when 2 then "invoked twice"
597
- else "invoked #{@invocation_count} times"
633
+ message = "#{@cardinality.anticipated_times}, #{@cardinality.invoked_times}: #{method_signature}"
634
+ message << "; #{@ordering_constraints.map(&:mocha_inspect).join('; ')}" unless @ordering_constraints.empty?
635
+ if Mocha.configuration.display_matching_invocations_on_failure?
636
+ message << @cardinality.actual_invocations
598
637
  end
599
- message << ": "
600
- message << method_signature
601
- message << "; #{@ordering_constraints.map { |oc| oc.mocha_inspect }.join("; ")}" unless @ordering_constraints.empty?
602
638
  message
603
639
  end
604
640
 
605
641
  # @private
606
642
  def method_signature
607
- "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}"
643
+ signature = "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}"
644
+ signature << " #{@block_matcher.mocha_inspect}" if @block_matcher.mocha_inspect
645
+ signature
608
646
  end
609
-
610
647
  end
611
-
612
648
  end
@@ -4,5 +4,5 @@ module Mocha
4
4
  # Authors of test libraries may use +Mocha::ExpectationErrorFactory+ to have Mocha raise a different exception.
5
5
  #
6
6
  # @see Mocha::ExpectationErrorFactory
7
- class ExpectationError < Exception; end
7
+ class ExpectationError < Exception; end # rubocop:disable Lint/InheritException
8
8
  end
@@ -2,7 +2,6 @@ require 'mocha/backtrace_filter'
2
2
  require 'mocha/expectation_error'
3
3
 
4
4
  module Mocha
5
-
6
5
  # This factory determines what class of exception should be raised when Mocha detects a test failure.
7
6
  #
8
7
  # This class should only be used by authors of test libraries and not by typical "users" of Mocha.
@@ -1,7 +1,5 @@
1
1
  module Mocha
2
-
3
2
  class ExpectationList
4
-
5
3
  def initialize(expectations = [])
6
4
  @expectations = expectations
7
5
  end
@@ -19,12 +17,12 @@ module Mocha
19
17
  @expectations.any? { |expectation| expectation.matches_method?(method_name) }
20
18
  end
21
19
 
22
- def match(method_name, *arguments)
23
- matching_expectations(method_name, *arguments).first
20
+ def match(invocation)
21
+ matching_expectations(invocation).first
24
22
  end
25
23
 
26
- def match_allowing_invocation(method_name, *arguments)
27
- matching_expectations(method_name, *arguments).detect { |e| e.invocations_allowed? }
24
+ def match_allowing_invocation(invocation)
25
+ matching_expectations(invocation).detect(&:invocations_allowed?)
28
26
  end
29
27
 
30
28
  def verified?(assertion_counter = nil)
@@ -48,15 +46,13 @@ module Mocha
48
46
  end
49
47
 
50
48
  def +(other)
51
- self.class.new(self.to_a + other.to_a)
49
+ self.class.new(to_a + other.to_a)
52
50
  end
53
51
 
54
52
  private
55
53
 
56
- def matching_expectations(method_name, *arguments)
57
- @expectations.select { |e| e.match?(method_name, *arguments) }
54
+ def matching_expectations(invocation)
55
+ @expectations.select { |e| e.match?(invocation) }
58
56
  end
59
-
60
57
  end
61
-
62
58
  end
data/lib/mocha/hooks.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'mocha/mockery'
2
2
 
3
3
  module Mocha
4
-
5
4
  # Integration hooks for test library authors.
6
5
  #
7
6
  # The methods in this module should be called from test libraries wishing to integrate with Mocha.
@@ -21,6 +20,7 @@ module Mocha
21
20
  #
22
21
  # This method should be called before each individual test starts (including before any "setup" code).
23
22
  def mocha_setup
23
+ Mockery.setup
24
24
  end
25
25
 
26
26
  # Verifies that all mock expectations have been met (only for use by authors of test libraries).
@@ -37,8 +37,6 @@ module Mocha
37
37
  # This method should be called after each individual test has finished (including after any "teardown" code).
38
38
  def mocha_teardown
39
39
  Mockery.teardown
40
- ensure
41
- Mockery.reset_instance
42
40
  end
43
41
  end
44
42
  end
@@ -1,7 +1,5 @@
1
1
  module Mocha
2
-
3
2
  class InStateOrderingConstraint
4
-
5
3
  def initialize(state_predicate)
6
4
  @state_predicate = state_predicate
7
5
  end
@@ -13,7 +11,5 @@ module Mocha
13
11
  def mocha_inspect
14
12
  "when #{@state_predicate.mocha_inspect}"
15
13
  end
16
-
17
14
  end
18
-
19
15
  end
data/lib/mocha/inspect.rb CHANGED
@@ -1,67 +1,59 @@
1
1
  require 'date'
2
2
 
3
3
  module Mocha
4
-
5
- module ObjectMethods
6
- def mocha_inspect
7
- address = self.__id__ * 2
8
- address += 0x100000000 if address < 0
9
- inspect =~ /#</ ? "#<#{self.class}:0x#{'%x' % address}>" : inspect
4
+ module Inspect
5
+ module ObjectMethods
6
+ def mocha_inspect
7
+ address = __id__ * 2
8
+ address += 0x100000000 if address < 0
9
+ inspect =~ /#</ ? "#<#{self.class}:0x#{Kernel.format('%x', address)}>" : inspect
10
+ end
10
11
  end
11
- end
12
12
 
13
- module StringMethods
14
- def mocha_inspect
15
- inspect.gsub(/\"/, "'")
13
+ module ArrayMethods
14
+ def mocha_inspect(wrapped = true)
15
+ unwrapped = collect(&:mocha_inspect).join(', ')
16
+ wrapped ? "[#{unwrapped}]" : unwrapped
17
+ end
16
18
  end
17
- end
18
19
 
19
- module ArrayMethods
20
- def mocha_inspect
21
- "[#{collect { |member| member.mocha_inspect }.join(', ')}]"
20
+ module HashMethods
21
+ def mocha_inspect(wrapped = true)
22
+ unwrapped = collect { |key, value| "#{key.mocha_inspect} => #{value.mocha_inspect}" }.join(', ')
23
+ wrapped ? "{#{unwrapped}}" : unwrapped
24
+ end
22
25
  end
23
- end
24
26
 
25
- module HashMethods
26
- def mocha_inspect
27
- "{#{collect { |key, value| "#{key.mocha_inspect} => #{value.mocha_inspect}" }.join(', ')}}"
27
+ module TimeMethods
28
+ def mocha_inspect
29
+ "#{inspect} (#{to_f} secs)"
30
+ end
28
31
  end
29
- end
30
32
 
31
- module TimeMethods
32
- def mocha_inspect
33
- "#{inspect} (#{to_f} secs)"
33
+ module DateMethods
34
+ def mocha_inspect
35
+ to_s
36
+ end
34
37
  end
35
38
  end
36
-
37
- module DateMethods
38
- def mocha_inspect
39
- to_s
40
- end
41
- end
42
-
43
39
  end
44
40
 
45
41
  class Object
46
- include Mocha::ObjectMethods
47
- end
48
-
49
- class String
50
- include Mocha::StringMethods
42
+ include Mocha::Inspect::ObjectMethods
51
43
  end
52
44
 
53
45
  class Array
54
- include Mocha::ArrayMethods
46
+ include Mocha::Inspect::ArrayMethods
55
47
  end
56
48
 
57
49
  class Hash
58
- include Mocha::HashMethods
50
+ include Mocha::Inspect::HashMethods
59
51
  end
60
52
 
61
53
  class Time
62
- include Mocha::TimeMethods
54
+ include Mocha::Inspect::TimeMethods
63
55
  end
64
56
 
65
57
  class Date
66
- include Mocha::DateMethods
58
+ include Mocha::Inspect::DateMethods
67
59
  end
@@ -1,16 +1,23 @@
1
- require 'mocha/class_method'
1
+ require 'mocha/stubbed_method'
2
2
 
3
3
  module Mocha
4
+ class InstanceMethod < StubbedMethod
5
+ private
4
6
 
5
- class InstanceMethod < ClassMethod
7
+ def mock_owner
8
+ stubbee
9
+ end
6
10
 
7
- def method_exists?(method)
8
- return true if stubbee.public_methods(false).include?(method)
9
- return true if stubbee.protected_methods(false).include?(method)
10
- return true if stubbee.private_methods(false).include?(method)
11
- return false
11
+ def method_body(method)
12
+ PRE_RUBY_V19 ? proc { |*args, &block| method.call(*args, &block) } : method
12
13
  end
13
14
 
14
- end
15
+ def stubbee_method(method_name)
16
+ stubbee._method(method_name)
17
+ end
15
18
 
19
+ def original_method_owner
20
+ stubbee.singleton_class
21
+ end
22
+ end
16
23
  end
@@ -5,7 +5,6 @@ require 'mocha/expectation_error_factory'
5
5
  module Mocha
6
6
  module Integration
7
7
  module MiniTest
8
-
9
8
  # Integrates Mocha into recent versions of MiniTest.
10
9
  #
11
10
  # See the source code for an example of how to integrate Mocha into a test library.
@@ -19,11 +18,11 @@ module Mocha
19
18
 
20
19
  # @private
21
20
  def self.description
22
- "adapter for MiniTest gem >= v3.3.0"
21
+ 'adapter for MiniTest gem >= v3.3.0'
23
22
  end
24
23
 
25
24
  # @private
26
- def self.included(mod)
25
+ def self.included(_mod)
27
26
  Mocha::ExpectationErrorFactory.exception_class = ::MiniTest::Assertion
28
27
  end
29
28
 
@@ -51,4 +50,3 @@ module Mocha
51
50
  end
52
51
  end
53
52
  end
54
-
@@ -4,7 +4,7 @@ module Mocha
4
4
  module Integration
5
5
  module MiniTest
6
6
  def self.translate(exception)
7
- return exception unless exception.kind_of?(::Mocha::ExpectationError)
7
+ return exception unless exception.is_a?(::Mocha::ExpectationError)
8
8
  translated_exception = ::MiniTest::Assertion.new(exception.message)
9
9
  translated_exception.set_backtrace(exception.backtrace)
10
10
  translated_exception