mocha 1.4.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +1 -0
  3. data/.rubocop.yml +53 -0
  4. data/.rubocop_todo.yml +27 -0
  5. data/.yardopts +1 -1
  6. data/CONTRIBUTING.md +4 -9
  7. data/COPYING.md +2 -2
  8. data/Gemfile +27 -0
  9. data/MIT-LICENSE.md +1 -1
  10. data/README.md +88 -117
  11. data/RELEASE.md +340 -0
  12. data/Rakefile +53 -52
  13. data/gemfiles/Gemfile.minitest.latest +1 -0
  14. data/gemfiles/Gemfile.test-unit.latest +2 -5
  15. data/lib/mocha/any_instance_method.rb +9 -62
  16. data/lib/mocha/api.rb +84 -74
  17. data/lib/mocha/argument_iterator.rb +4 -8
  18. data/lib/mocha/backtrace_filter.rb +3 -7
  19. data/lib/mocha/block_matcher.rb +31 -0
  20. data/lib/mocha/cardinality.rb +60 -49
  21. data/lib/mocha/central.rb +21 -12
  22. data/lib/mocha/change_state_side_effect.rb +0 -4
  23. data/lib/mocha/class_methods.rb +19 -21
  24. data/lib/mocha/configuration.rb +317 -52
  25. data/lib/mocha/debug.rb +2 -4
  26. data/lib/mocha/deprecation.rb +6 -12
  27. data/lib/mocha/detection/mini_test.rb +0 -2
  28. data/lib/mocha/detection/test_unit.rb +3 -5
  29. data/lib/mocha/error_with_filtered_backtrace.rb +13 -0
  30. data/lib/mocha/exception_raiser.rb +4 -6
  31. data/lib/mocha/expectation.rb +186 -95
  32. data/lib/mocha/expectation_error.rb +1 -1
  33. data/lib/mocha/expectation_error_factory.rb +0 -1
  34. data/lib/mocha/expectation_list.rb +7 -11
  35. data/lib/mocha/hooks.rb +1 -3
  36. data/lib/mocha/in_state_ordering_constraint.rb +0 -4
  37. data/lib/mocha/inspect.rb +30 -28
  38. data/lib/mocha/instance_method.rb +14 -3
  39. data/lib/mocha/integration/mini_test/adapter.rb +3 -5
  40. data/lib/mocha/integration/mini_test/exception_translation.rb +1 -1
  41. data/lib/mocha/integration/mini_test.rb +10 -31
  42. data/lib/mocha/integration/monkey_patcher.rb +5 -7
  43. data/lib/mocha/integration/test_unit/adapter.rb +8 -9
  44. data/lib/mocha/integration/test_unit.rb +10 -26
  45. data/lib/mocha/invocation.rb +73 -0
  46. data/lib/mocha/is_a.rb +0 -2
  47. data/lib/mocha/logger.rb +0 -4
  48. data/lib/mocha/macos_version.rb +5 -0
  49. data/lib/mocha/method_matcher.rb +1 -5
  50. data/lib/mocha/minitest.rb +5 -2
  51. data/lib/mocha/mock.rb +104 -68
  52. data/lib/mocha/mockery.rb +70 -99
  53. data/lib/mocha/names.rb +2 -12
  54. data/lib/mocha/not_initialized_error.rb +7 -0
  55. data/lib/mocha/object_methods.rb +25 -31
  56. data/lib/mocha/parameter_matchers/all_of.rb +2 -8
  57. data/lib/mocha/parameter_matchers/any_of.rb +2 -8
  58. data/lib/mocha/parameter_matchers/any_parameters.rb +3 -9
  59. data/lib/mocha/parameter_matchers/anything.rb +2 -8
  60. data/lib/mocha/parameter_matchers/base.rb +7 -13
  61. data/lib/mocha/parameter_matchers/equals.rb +0 -6
  62. data/lib/mocha/parameter_matchers/equivalent_uri.rb +3 -13
  63. data/lib/mocha/parameter_matchers/has_entries.rb +2 -7
  64. data/lib/mocha/parameter_matchers/has_entry.rb +26 -21
  65. data/lib/mocha/parameter_matchers/has_key.rb +2 -7
  66. data/lib/mocha/parameter_matchers/has_keys.rb +53 -0
  67. data/lib/mocha/parameter_matchers/has_value.rb +2 -7
  68. data/lib/mocha/parameter_matchers/includes.rb +4 -6
  69. data/lib/mocha/parameter_matchers/instance_methods.rb +27 -0
  70. data/lib/mocha/parameter_matchers/instance_of.rb +0 -6
  71. data/lib/mocha/parameter_matchers/is_a.rb +2 -7
  72. data/lib/mocha/parameter_matchers/kind_of.rb +2 -6
  73. data/lib/mocha/parameter_matchers/not.rb +2 -7
  74. data/lib/mocha/parameter_matchers/optionally.rb +4 -10
  75. data/lib/mocha/parameter_matchers/positional_or_keyword_hash.rb +64 -0
  76. data/lib/mocha/parameter_matchers/regexp_matches.rb +0 -6
  77. data/lib/mocha/parameter_matchers/responds_with.rb +3 -8
  78. data/lib/mocha/parameter_matchers/yaml_equivalent.rb +2 -6
  79. data/lib/mocha/parameter_matchers.rb +2 -3
  80. data/lib/mocha/parameters_matcher.rb +8 -11
  81. data/lib/mocha/raised_exception.rb +11 -0
  82. data/lib/mocha/receivers.rb +10 -14
  83. data/lib/mocha/return_values.rb +4 -8
  84. data/lib/mocha/ruby_version.rb +1 -2
  85. data/lib/mocha/sequence.rb +4 -9
  86. data/lib/mocha/single_return_value.rb +2 -5
  87. data/lib/mocha/state_machine.rb +33 -46
  88. data/lib/mocha/stubbed_method.rb +88 -0
  89. data/lib/mocha/stubbing_error.rb +2 -13
  90. data/lib/mocha/test_unit.rb +5 -2
  91. data/lib/mocha/thrower.rb +4 -6
  92. data/lib/mocha/thrown_object.rb +12 -0
  93. data/lib/mocha/version.rb +1 -1
  94. data/lib/mocha/yield_parameters.rb +7 -17
  95. data/mocha.gemspec +15 -65
  96. metadata +27 -257
  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 -5
  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 -58
  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 -301
  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 -201
  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 -75
  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 -76
  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 -16
  205. data/test/execution_point.rb +0 -38
  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 -136
  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 -229
  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 -350
  234. data/test/unit/mockery_test.rb +0 -157
  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/equivalent_uri_test.rb +0 -51
  245. data/test/unit/parameter_matchers/has_entries_test.rb +0 -51
  246. data/test/unit/parameter_matchers/has_entry_test.rb +0 -129
  247. data/test/unit/parameter_matchers/has_key_test.rb +0 -55
  248. data/test/unit/parameter_matchers/has_value_test.rb +0 -57
  249. data/test/unit/parameter_matchers/includes_test.rb +0 -107
  250. data/test/unit/parameter_matchers/instance_of_test.rb +0 -25
  251. data/test/unit/parameter_matchers/is_a_test.rb +0 -25
  252. data/test/unit/parameter_matchers/kind_of_test.rb +0 -25
  253. data/test/unit/parameter_matchers/not_test.rb +0 -26
  254. data/test/unit/parameter_matchers/regexp_matches_test.rb +0 -46
  255. data/test/unit/parameter_matchers/responds_with_test.rb +0 -32
  256. data/test/unit/parameter_matchers/stub_matcher.rb +0 -27
  257. data/test/unit/parameter_matchers/yaml_equivalent_test.rb +0 -25
  258. data/test/unit/parameters_matcher_test.rb +0 -121
  259. data/test/unit/receivers_test.rb +0 -66
  260. data/test/unit/return_values_test.rb +0 -63
  261. data/test/unit/sequence_test.rb +0 -104
  262. data/test/unit/single_return_value_test.rb +0 -14
  263. data/test/unit/single_yield_test.rb +0 -18
  264. data/test/unit/state_machine_test.rb +0 -98
  265. data/test/unit/string_inspect_test.rb +0 -11
  266. data/test/unit/thrower_test.rb +0 -20
  267. data/test/unit/yield_parameters_test.rb +0 -93
  268. data/yard-templates/default/layout/html/google_analytics.erb +0 -11
  269. data/yard-templates/default/layout/html/setup.rb +0 -6
@@ -1,89 +1,354 @@
1
+ require 'mocha/ruby_version'
2
+
1
3
  module Mocha
4
+ # Allows setting of configuration options. See {Configuration} for the available options.
5
+ #
6
+ # Typically the configuration is set globally in a +test_helper.rb+ or +spec_helper.rb+ file.
7
+ #
8
+ # @see Configuration
9
+ #
10
+ # @yieldparam configuration [Configuration] the configuration for modification
11
+ #
12
+ # @example Setting multiple configuration options
13
+ # Mocha.configure do |c|
14
+ # c.stubbing_method_unnecessarily = :prevent
15
+ # c.stubbing_method_on_non_mock_object = :warn
16
+ # c.stubbing_method_on_nil = :allow
17
+ # end
18
+ #
19
+ def self.configure
20
+ yield configuration
21
+ end
2
22
 
3
- # Configuration settings.
4
- class Configuration
23
+ # @private
24
+ def self.configuration
25
+ Configuration.configuration
26
+ end
5
27
 
28
+ # This class provides a number of ways to configure the library.
29
+ #
30
+ # Typically the configuration is set globally in a +test_helper.rb+ or +spec_helper.rb+ file.
31
+ #
32
+ # @example Setting multiple configuration options
33
+ # Mocha.configure do |c|
34
+ # c.stubbing_method_unnecessarily = :prevent
35
+ # c.stubbing_method_on_non_mock_object = :warn
36
+ # c.stubbing_method_on_nil = :allow
37
+ # end
38
+ #
39
+ class Configuration
40
+ # @private
6
41
  DEFAULTS = {
7
- :stubbing_method_unnecessarily => :allow,
8
- :stubbing_method_on_non_mock_object => :allow,
9
- :stubbing_non_existent_method => :allow,
10
- :stubbing_non_public_method => :allow,
11
- :stubbing_method_on_nil => :prevent,
12
- }
42
+ stubbing_method_unnecessarily: :allow,
43
+ stubbing_method_on_non_mock_object: :allow,
44
+ stubbing_non_existent_method: :allow,
45
+ stubbing_non_public_method: :allow,
46
+ stubbing_method_on_nil: :prevent,
47
+ display_matching_invocations_on_failure: false,
48
+ strict_keyword_argument_matching: false
49
+ }.freeze
13
50
 
14
- class << self
51
+ attr_reader :options
52
+ protected :options
15
53
 
16
- # Allow the specified +action+.
17
- #
18
- # @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+, +:stubbing_method_on_nil+.
19
- # @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block.
20
- def allow(action, &block)
21
- change_config action, :allow, &block
22
- end
54
+ # @private
55
+ def initialize(options = {})
56
+ @options = DEFAULTS.merge(options)
57
+ end
23
58
 
24
- # @private
25
- def allow?(action)
26
- configuration[action] == :allow
27
- end
59
+ # @private
60
+ def initialize_copy(other)
61
+ @options = other.options.dup
62
+ end
28
63
 
29
- # Warn if the specified +action+ is attempted.
30
- #
31
- # @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+, +:stubbing_method_on_nil+.
32
- # @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block.
33
- def warn_when(action, &block)
34
- change_config action, :warn, &block
35
- end
64
+ # @private
65
+ def merge(other)
66
+ self.class.new(@options.merge(other.options))
67
+ end
36
68
 
37
- # @private
38
- def warn_when?(action)
39
- configuration[action] == :warn
40
- end
69
+ # Configure whether stubbing methods unnecessarily is allowed.
70
+ #
71
+ # This is useful for identifying unused stubs. Unused stubs are often accidentally introduced when code is {http://martinfowler.com/bliki/DefinitionOfRefactoring.html refactored}.
72
+ #
73
+ # When +value+ is +:allow+, do nothing. This is the default.
74
+ # When +value+ is +:warn+, display a warning.
75
+ # When +value+ is +:prevent+, raise a {StubbingError}.
76
+ #
77
+ # @param [Symbol] value one of +:allow+, +:warn+, +:prevent+.
78
+ #
79
+ # @example Preventing unnecessary stubbing of a method
80
+ # Mocha.configure do |c|
81
+ # c.stubbing_method_unnecessarily = :prevent
82
+ # end
83
+ #
84
+ # example = mock('example')
85
+ # example.stubs(:unused_stub)
86
+ # # => Mocha::StubbingError: stubbing method unnecessarily:
87
+ # # => #<Mock:example>.unused_stub(any_parameters)
88
+ #
89
+ def stubbing_method_unnecessarily=(value)
90
+ @options[:stubbing_method_unnecessarily] = value
91
+ end
41
92
 
42
- # Raise a {StubbingError} if if the specified +action+ is attempted.
43
- #
44
- # @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+, +:stubbing_method_on_nil+.
45
- # @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block.
46
- def prevent(action, &block)
47
- change_config action, :prevent, &block
48
- end
93
+ # @private
94
+ def stubbing_method_unnecessarily
95
+ @options[:stubbing_method_unnecessarily]
96
+ end
49
97
 
50
- # @private
51
- def prevent?(action)
52
- configuration[action] == :prevent
53
- end
98
+ # Configure whether stubbing methods on non-mock objects is allowed.
99
+ #
100
+ # If you like the idea of {http://www.jmock.org/oopsla2004.pdf mocking roles not objects} and {http://www.mockobjects.com/2007/04/test-smell-mocking-concrete-classes.html you don't like stubbing concrete classes}, this is the setting for you. However, while this restriction makes a lot of sense in Java with its {http://java.sun.com/docs/books/tutorial/java/concepts/interface.html explicit interfaces}, it may be moot in Ruby where roles are probably best represented as Modules.
101
+ #
102
+ # When +value+ is +:allow+, do nothing. This is the default.
103
+ # When +value+ is +:warn+, display a warning.
104
+ # When +value+ is +:prevent+, raise a {StubbingError}.
105
+ #
106
+ # @param [Symbol] value one of +:allow+, +:warn+, +:prevent+.
107
+ #
108
+ # @example Preventing stubbing of a method on a non-mock object
109
+ # Mocha.configure do |c|
110
+ # c.stubbing_method_on_non_mock_object = :prevent
111
+ # end
112
+ #
113
+ # class Example
114
+ # def example_method; end
115
+ # end
116
+ #
117
+ # example = Example.new
118
+ # example.stubs(:example_method)
119
+ # # => Mocha::StubbingError: stubbing method on non-mock object:
120
+ # # => #<Example:0x593620>.example_method
121
+ #
122
+ def stubbing_method_on_non_mock_object=(value)
123
+ @options[:stubbing_method_on_non_mock_object] = value
124
+ end
125
+
126
+ # @private
127
+ def stubbing_method_on_non_mock_object
128
+ @options[:stubbing_method_on_non_mock_object]
129
+ end
130
+
131
+ # Configure whether stubbing of non-existent methods is allowed.
132
+ #
133
+ # This is useful if you want to ensure that methods you're mocking really exist. A common criticism of unit tests with mock objects is that such a test may (incorrectly) pass when an equivalent non-mocking test would (correctly) fail. While you should always have some integration tests, particularly for critical business functionality, this Mocha configuration setting should catch scenarios when mocked methods and real methods have become misaligned.
134
+ #
135
+ # When +value+ is +:allow+, do nothing. This is the default.
136
+ # When +value+ is +:warn+, display a warning.
137
+ # When +value+ is +:prevent+, raise a {StubbingError}.
138
+ #
139
+ # @param [Symbol] value one of +:allow+, +:warn+, +:prevent+.
140
+ #
141
+ # @example Preventing stubbing of a non-existent method
142
+ #
143
+ # Mocha.configure do |c|
144
+ # c.stubbing_non_existent_method = :prevent
145
+ # end
146
+ #
147
+ # class Example
148
+ # end
149
+ #
150
+ # example = Example.new
151
+ # example.stubs(:method_that_doesnt_exist)
152
+ # # => Mocha::StubbingError: stubbing non-existent method:
153
+ # # => #<Example:0x593760>.method_that_doesnt_exist
154
+ #
155
+ def stubbing_non_existent_method=(value)
156
+ @options[:stubbing_non_existent_method] = value
157
+ end
158
+
159
+ # @private
160
+ def stubbing_non_existent_method
161
+ @options[:stubbing_non_existent_method]
162
+ end
54
163
 
164
+ # Configure whether stubbing of non-public methods is allowed.
165
+ #
166
+ # Many people think that it's good practice only to mock public methods. This is one way to prevent your tests being too tightly coupled to the internal implementation of a class. Such tests tend to be very brittle and not much use when refactoring.
167
+ #
168
+ # When +value+ is +:allow+, do nothing. This is the default.
169
+ # When +value+ is +:warn+, display a warning.
170
+ # When +value+ is +:prevent+, raise a {StubbingError}.
171
+ #
172
+ # @param [Symbol] value one of +:allow+, +:warn+, +:prevent+.
173
+ #
174
+ # @example Preventing stubbing of a non-public method
175
+ # Mocha.configure do |c|
176
+ # c.stubbing_non_public_method = :prevent
177
+ # end
178
+ #
179
+ # class Example
180
+ # def internal_method; end
181
+ # private :internal_method
182
+ # end
183
+ #
184
+ # example = Example.new
185
+ # example.stubs(:internal_method)
186
+ # # => Mocha::StubbingError: stubbing non-public method:
187
+ # # => #<Example:0x593530>.internal_method
188
+ #
189
+ def stubbing_non_public_method=(value)
190
+ @options[:stubbing_non_public_method] = value
191
+ end
192
+
193
+ # @private
194
+ def stubbing_non_public_method
195
+ @options[:stubbing_non_public_method]
196
+ end
197
+
198
+ # Configure whether stubbing methods on the +nil+ object is allowed.
199
+ #
200
+ # This is usually done accidentally, but there might be rare cases where it is intended.
201
+ #
202
+ # This option only works for Ruby < v2.2.0. In later versions of Ruby +nil+ is frozen and so a {StubbingError} will be raised if you attempt to stub a method on +nil+.
203
+ #
204
+ # When +value+ is +:allow+, do nothing.
205
+ # When +value+ is +:warn+, display a warning.
206
+ # When +value+ is +:prevent+, raise a {StubbingError}. This is the default.
207
+ #
208
+ # @param [Symbol] value one of +:allow+, +:warn+, +:prevent+.
209
+ #
210
+ def stubbing_method_on_nil=(value)
211
+ @options[:stubbing_method_on_nil] = value
212
+ end
213
+
214
+ # @private
215
+ def stubbing_method_on_nil
216
+ @options[:stubbing_method_on_nil]
217
+ end
218
+
219
+ # Display matching invocations alongside expectations on Mocha-related test failure.
220
+ #
221
+ # @param [Boolean] value +true+ to enable display of matching invocations; disabled by default.
222
+ #
223
+ # @example Enable display of matching invocations
224
+ # Mocha.configure do |c|
225
+ # c.display_matching_invocations_on_failure = true
226
+ # end
227
+ #
228
+ # foo = mock('foo')
229
+ # foo.expects(:bar)
230
+ # foo.stubs(:baz).returns('baz').raises(RuntimeError).throws(:tag, 'value')
231
+ #
232
+ # foo.baz(1, 2)
233
+ # assert_raises(RuntimeError) { foo.baz(3, 4) }
234
+ # assert_throws(:tag) { foo.baz(5, 6) }
235
+ #
236
+ # not all expectations were satisfied
237
+ # unsatisfied expectations:
238
+ # - expected exactly once, invoked never: #<Mock:foo>.bar
239
+ # satisfied expectations:
240
+ # - allowed any number of times, invoked 3 times: #<Mock:foo>.baz(any_parameters)
241
+ # - #<Mock:foo>.baz(1, 2) # => "baz"
242
+ # - #<Mock:foo>.baz(3, 4) # => raised RuntimeError
243
+ # - #<Mock:foo>.baz(5, 6) # => threw (:tag, "value")
244
+ def display_matching_invocations_on_failure=(value)
245
+ @options[:display_matching_invocations_on_failure] = value
246
+ end
247
+
248
+ # @private
249
+ def display_matching_invocations_on_failure?
250
+ @options[:display_matching_invocations_on_failure]
251
+ end
252
+
253
+ # Perform strict keyword argument comparison. Only supported in Ruby >= v2.7.
254
+ #
255
+ # When this option is set to +false+ a positional +Hash+ and a set of keyword arguments are treated the same during comparison, which can lead to misleading passing tests in Ruby >= v3.0 (see examples below). However, a deprecation warning will be displayed if a positional +Hash+ matches a set of keyword arguments or vice versa. This is because {#strict_keyword_argument_matching=} will default to +true+ in the future.
256
+ #
257
+ # For more details on keyword arguments in Ruby v3, refer to {https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0 this article}.
258
+ #
259
+ # Note that +Hash+-related matchers such as {ParameterMatchers#has_value} or {ParameterMatchers#has_key} will still treat a positional +Hash+ and a set of keyword arguments the same, so misleading passing tests are still possible when they are used.
260
+ #
261
+ # This configuration option is +false+ by default to enable gradual adoption, but will be +true+ by default in the future.
262
+ #
263
+ # @param [Boolean] value +true+ to enable strict keyword argument matching; +false+ by default.
264
+ #
265
+ # @example Loose keyword argument matching (default)
266
+ #
267
+ # class Example
268
+ # def foo(a, bar:); end
269
+ # end
270
+ #
271
+ # example = Example.new
272
+ # example.expects(:foo).with('a', bar: 'b')
273
+ # example.foo('a', { bar: 'b' })
274
+ # # This passes the test, but would result in an ArgumentError in practice
275
+ #
276
+ # @example Strict keyword argument matching
277
+ #
278
+ # Mocha.configure do |c|
279
+ # c.strict_keyword_argument_matching = true
280
+ # end
281
+ #
282
+ # class Example
283
+ # def foo(a, bar:); end
284
+ # end
285
+ #
286
+ # example = Example.new
287
+ # example.expects(:foo).with('a', bar: 'b')
288
+ # example.foo('a', { bar: 'b' })
289
+ # # This now fails as expected
290
+ def strict_keyword_argument_matching=(value)
291
+ raise 'Strict keyword argument matching requires Ruby 2.7 and above.' unless Mocha::RUBY_V27_PLUS
292
+ @options[:strict_keyword_argument_matching] = value
293
+ end
294
+
295
+ # @private
296
+ def strict_keyword_argument_matching?
297
+ @options[:strict_keyword_argument_matching]
298
+ end
299
+
300
+ class << self
55
301
  # @private
56
302
  def reset_configuration
57
303
  @configuration = nil
58
304
  end
59
305
 
60
- private
306
+ # Temporarily modify {Configuration} options.
307
+ #
308
+ # The supplied +temporary_options+ will override the current configuration for the duration of the supplied block.
309
+ # The configuration will be returned to its original state when the block returns.
310
+ #
311
+ # @param [Hash] temporary_options the configuration options to apply for the duration of the block.
312
+ # @yield block during which the configuration change will be in force.
313
+ #
314
+ # @example Temporarily allow stubbing of +nil+
315
+ # Mocha::Configuration.override(stubbing_method_on_nil: :allow) do
316
+ # nil.stubs(:foo)
317
+ # end
318
+ def override(temporary_options)
319
+ original_configuration = configuration
320
+ @configuration = configuration.merge(new(temporary_options))
321
+ yield
322
+ ensure
323
+ @configuration = original_configuration
324
+ end
61
325
 
62
326
  # @private
63
327
  def configuration
64
- @configuration ||= DEFAULTS.dup
328
+ @configuration ||= new
65
329
  end
66
330
 
331
+ private
332
+
67
333
  # @private
68
334
  def change_config(action, new_value, &block)
69
335
  if block_given?
70
336
  temporarily_change_config action, new_value, &block
71
337
  else
72
- configuration[action] = new_value
338
+ configuration.send("#{action}=".to_sym, new_value)
73
339
  end
74
340
  end
75
341
 
76
342
  # @private
77
- def temporarily_change_config(action, new_value, &block)
78
- original_value = configuration[action]
79
- configuration[action] = new_value
343
+ def temporarily_change_config(action, new_value)
344
+ original_configuration = configuration
345
+ new_configuration = configuration.dup
346
+ new_configuration.send("#{action}=".to_sym, new_value)
347
+ @configuration = new_configuration
80
348
  yield
81
349
  ensure
82
- configuration[action] = original_value
350
+ @configuration = original_configuration
83
351
  end
84
-
85
352
  end
86
-
87
353
  end
88
-
89
354
  end
data/lib/mocha/debug.rb CHANGED
@@ -1,11 +1,9 @@
1
1
  module Mocha
2
2
  module Debug
3
- OPTIONS = (ENV['MOCHA_OPTIONS'] || '').split(',').inject({}) do |hash, key|
4
- hash[key] = true; hash
5
- end.freeze
3
+ OPTIONS = (ENV['MOCHA_OPTIONS'] || '').split(',').freeze
6
4
 
7
5
  def self.puts(message)
8
- $stderr.puts(message) if OPTIONS['debug']
6
+ warn(message) if OPTIONS.include?('debug')
9
7
  end
10
8
  end
11
9
  end
@@ -1,27 +1,21 @@
1
1
  require 'mocha/backtrace_filter'
2
2
 
3
3
  module Mocha
4
-
5
4
  class Deprecation
6
-
7
5
  class << self
8
-
9
6
  attr_accessor :mode, :messages
10
7
 
11
- def warning(message)
8
+ def warning(*messages)
9
+ message = messages.join
12
10
  @messages << message
13
- unless mode == :disabled
14
- filter = BacktraceFilter.new
15
- location = filter.filtered(caller)[0]
16
- $stderr.puts "Mocha deprecation warning at #{location}: #{message}"
17
- end
11
+ return if mode == :disabled
12
+ filter = BacktraceFilter.new
13
+ location = filter.filtered(caller)[0]
14
+ warn "Mocha deprecation warning at #{location}: #{message}"
18
15
  end
19
-
20
16
  end
21
17
 
22
18
  self.mode = :enabled
23
19
  self.messages = []
24
-
25
20
  end
26
-
27
21
  end
@@ -6,8 +6,6 @@ module Mocha
6
6
  ::Minitest::Test
7
7
  elsif defined?(::MiniTest::Unit::TestCase)
8
8
  ::MiniTest::Unit::TestCase
9
- else
10
- nil
11
9
  end
12
10
  end
13
11
 
@@ -3,11 +3,9 @@ module Mocha
3
3
  module TestUnit
4
4
  def self.testcase
5
5
  if defined?(::Test::Unit::TestCase) &&
6
- !(defined?(::MiniTest::Unit::TestCase) && (::Test::Unit::TestCase < ::MiniTest::Unit::TestCase)) &&
7
- !(defined?(::MiniTest::Spec) && (::Test::Unit::TestCase < ::MiniTest::Spec))
6
+ !(defined?(::MiniTest::Unit::TestCase) && (::Test::Unit::TestCase < ::MiniTest::Unit::TestCase)) &&
7
+ !(defined?(::MiniTest::Spec) && (::Test::Unit::TestCase < ::MiniTest::Spec))
8
8
  ::Test::Unit::TestCase
9
- else
10
- nil
11
9
  end
12
10
  end
13
11
 
@@ -16,7 +14,7 @@ module Mocha
16
14
  if testcase
17
15
  begin
18
16
  require 'test/unit/version'
19
- rescue LoadError
17
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
20
18
  end
21
19
  if defined?(::Test::Unit::VERSION)
22
20
  version = ::Test::Unit::VERSION
@@ -0,0 +1,13 @@
1
+ require 'mocha/backtrace_filter'
2
+
3
+ module Mocha
4
+ # @private
5
+ class ErrorWithFilteredBacktrace < StandardError
6
+ # @private
7
+ def initialize(message = nil, backtrace = [])
8
+ super(message)
9
+ filter = BacktraceFilter.new
10
+ set_backtrace(filter.filtered(backtrace))
11
+ end
12
+ end
13
+ end
@@ -1,17 +1,15 @@
1
1
  module Mocha
2
-
3
2
  class ExceptionRaiser
4
-
5
3
  def initialize(exception, message)
6
- @exception, @message = exception, message
4
+ @exception = exception
5
+ @message = message
7
6
  end
8
7
 
9
- def evaluate
8
+ def evaluate(invocation)
9
+ invocation.raised(@exception)
10
10
  raise @exception, @exception.to_s if @exception.is_a?(Module) && (@exception < Interrupt)
11
11
  raise @exception, @message if @message
12
12
  raise @exception
13
13
  end
14
-
15
14
  end
16
-
17
15
  end