mocha 0.10.5 → 1.13.0

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