mocha 0.4.0 → 0.5.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 (78) hide show
  1. data/Rakefile +28 -10
  2. data/examples/stubba.rb +1 -1
  3. data/lib/mocha/auto_verify.rb +6 -6
  4. data/lib/mocha/deprecation.rb +22 -0
  5. data/lib/mocha/exception_raiser.rb +17 -0
  6. data/lib/mocha/expectation.rb +167 -84
  7. data/lib/mocha/infinite_range.rb +4 -6
  8. data/lib/mocha/inspect.rb +3 -1
  9. data/lib/mocha/is_a.rb +9 -0
  10. data/lib/mocha/missing_expectation.rb +27 -0
  11. data/lib/mocha/mock.rb +191 -5
  12. data/lib/mocha/multiple_yields.rb +20 -0
  13. data/lib/mocha/no_yields.rb +11 -0
  14. data/lib/mocha/object.rb +11 -1
  15. data/lib/mocha/parameter_matchers.rb +9 -0
  16. data/lib/mocha/parameter_matchers/all_of.rb +39 -0
  17. data/lib/mocha/parameter_matchers/any_of.rb +44 -0
  18. data/lib/mocha/parameter_matchers/anything.rb +30 -0
  19. data/lib/mocha/parameter_matchers/has_entry.rb +39 -0
  20. data/lib/mocha/parameter_matchers/has_key.rb +39 -0
  21. data/lib/mocha/parameter_matchers/has_value.rb +39 -0
  22. data/lib/mocha/parameter_matchers/includes.rb +37 -0
  23. data/lib/mocha/return_values.rb +31 -0
  24. data/lib/mocha/single_return_value.rb +24 -0
  25. data/lib/mocha/single_yield.rb +18 -0
  26. data/lib/mocha/standalone.rb +2 -0
  27. data/lib/mocha/stub.rb +18 -0
  28. data/lib/mocha/yield_parameters.rb +31 -0
  29. data/test/{mocha_acceptance_test.rb → acceptance/mocha_acceptance_test.rb} +1 -1
  30. data/test/acceptance/mocked_methods_dispatch_acceptance_test.rb +72 -0
  31. data/test/acceptance/parameter_matcher_acceptance_test.rb +63 -0
  32. data/test/{standalone_acceptance_test.rb → acceptance/standalone_acceptance_test.rb} +22 -1
  33. data/test/{stubba_acceptance_test.rb → acceptance/stubba_acceptance_test.rb} +1 -1
  34. data/test/deprecation_disabler.rb +15 -0
  35. data/test/{mocha_test_result_integration_test.rb → integration/mocha_test_result_integration_test.rb} +1 -1
  36. data/test/{stubba_integration_test.rb → integration/stubba_integration_test.rb} +1 -1
  37. data/test/{stubba_test_result_integration_test.rb → integration/stubba_test_result_integration_test.rb} +1 -1
  38. data/test/test_helper.rb +8 -0
  39. data/test/test_runner.rb +31 -0
  40. data/test/{mocha → unit}/any_instance_method_test.rb +0 -0
  41. data/test/unit/array_inspect_test.rb +16 -0
  42. data/test/{mocha → unit}/auto_verify_test.rb +0 -0
  43. data/test/{mocha → unit}/central_test.rb +0 -0
  44. data/test/{mocha → unit}/class_method_test.rb +0 -0
  45. data/test/unit/date_time_inspect_test.rb +21 -0
  46. data/test/unit/expectation_raiser_test.rb +28 -0
  47. data/test/{mocha → unit}/expectation_test.rb +105 -63
  48. data/test/unit/hash_inspect_test.rb +16 -0
  49. data/test/{mocha → unit}/infinite_range_test.rb +8 -5
  50. data/test/{mocha → unit}/metaclass_test.rb +0 -0
  51. data/test/unit/missing_expectation_test.rb +51 -0
  52. data/test/unit/mock_test.rb +351 -0
  53. data/test/unit/multiple_yields_test.rb +18 -0
  54. data/test/unit/no_yield_test.rb +18 -0
  55. data/test/unit/object_inspect_test.rb +35 -0
  56. data/test/{mocha → unit}/object_test.rb +0 -0
  57. data/test/unit/parameter_matchers/all_of_test.rb +26 -0
  58. data/test/unit/parameter_matchers/any_of_test.rb +26 -0
  59. data/test/unit/parameter_matchers/anything_test.rb +21 -0
  60. data/test/unit/parameter_matchers/has_entry_test.rb +25 -0
  61. data/test/unit/parameter_matchers/has_key_test.rb +25 -0
  62. data/test/unit/parameter_matchers/has_value_test.rb +25 -0
  63. data/test/unit/parameter_matchers/includes_test.rb +25 -0
  64. data/test/unit/parameter_matchers/stub_matcher.rb +22 -0
  65. data/test/{mocha → unit}/pretty_parameters_test.rb +0 -0
  66. data/test/unit/return_values_test.rb +63 -0
  67. data/test/{mocha → unit}/setup_and_teardown_test.rb +0 -0
  68. data/test/unit/single_return_value_test.rb +33 -0
  69. data/test/unit/single_yield_test.rb +18 -0
  70. data/test/unit/string_inspect_test.rb +11 -0
  71. data/test/unit/stub_test.rb +24 -0
  72. data/test/unit/yield_parameters_test.rb +93 -0
  73. metadata +117 -73
  74. data/lib/mocha/mock_methods.rb +0 -122
  75. data/test/all_tests.rb +0 -75
  76. data/test/mocha/inspect_test.rb +0 -90
  77. data/test/mocha/mock_methods_test.rb +0 -235
  78. data/test/mocha/mock_test.rb +0 -84
data/Rakefile CHANGED
@@ -1,19 +1,37 @@
1
1
  require 'rubygems'
2
2
  require 'rake/rdoctask'
3
3
  require 'rake/gempackagetask'
4
+ require 'rake/testtask'
4
5
  require 'rake/contrib/sshpublisher'
5
6
 
6
7
  module Mocha
7
- VERSION = "0.4.0"
8
+ VERSION = "0.5.0"
8
9
  end
9
10
 
10
- desc "Default task is currently to run all tests"
11
+ desc "Run all tests"
11
12
  task :default => :test_all
12
13
 
13
- desc "Run all tests"
14
- task :test_all do
15
- $: << "#{File.dirname(__FILE__)}/test"
16
- require 'test/all_tests'
14
+ task :test_all => [:test_unit, :test_integration, :test_acceptance]
15
+
16
+ desc "Run unit tests"
17
+ Rake::TestTask.new(:test_unit) do |t|
18
+ t.libs << 'test'
19
+ t.test_files = FileList['test/unit/**/*_test.rb']
20
+ t.verbose = true
21
+ end
22
+
23
+ desc "Run integration tests"
24
+ Rake::TestTask.new(:test_integration) do |t|
25
+ t.libs << 'test'
26
+ t.test_files = FileList['test/integration/*_test.rb']
27
+ t.verbose = true
28
+ end
29
+
30
+ desc "Run acceptance tests"
31
+ Rake::TestTask.new(:test_acceptance) do |t|
32
+ t.libs << 'test'
33
+ t.test_files = FileList['test/acceptance/*_test.rb']
34
+ t.verbose = true
17
35
  end
18
36
 
19
37
  desc 'Generate RDoc'
@@ -21,9 +39,8 @@ Rake::RDocTask.new do |task|
21
39
  task.main = 'README'
22
40
  task.title = 'Mocha'
23
41
  task.rdoc_dir = 'doc'
24
- task.template = "html_with_google_analytics"
25
- task.options << "--line-numbers" << "--inline-source"
26
- task.rdoc_files.include('README', 'RELEASE', 'COPYING', 'MIT-LICENSE', 'agiledox.txt', 'lib/mocha/auto_verify.rb', 'lib/mocha/mock_methods.rb', 'lib/mocha/expectation.rb', 'lib/mocha/object.rb')
42
+ task.template = File.expand_path(File.join(File.dirname(__FILE__), "templates", "html_with_google_analytics"))
43
+ task.rdoc_files.include('README', 'RELEASE', 'COPYING', 'MIT-LICENSE', 'agiledox.txt', 'lib/mocha/auto_verify.rb', 'lib/mocha/mock.rb', 'lib/mocha/expectation.rb', 'lib/mocha/object.rb', 'lib/mocha/parameter_matchers.rb', 'lib/mocha/parameter_matchers')
27
44
  end
28
45
  task :rdoc => :examples
29
46
 
@@ -50,6 +67,7 @@ end
50
67
 
51
68
  desc "Convert example ruby files to syntax-highlighted html"
52
69
  task :examples do
70
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "vendor", "coderay-0.7.4.215", "lib"))
53
71
  require 'coderay'
54
72
  mkdir_p 'doc/examples'
55
73
  File.open('doc/examples/coderay.css', 'w') do |output|
@@ -89,7 +107,6 @@ specification = Gem::Specification.new do |s|
89
107
 
90
108
  s.autorequire = 'mocha'
91
109
  s.files = FileList['{lib,test,examples}/**/*.rb', '[A-Z]*'].exclude('TODO').to_a
92
- s.test_file = "test/all_tests.rb"
93
110
  end
94
111
 
95
112
  Rake::GemPackageTask.new(specification) do |package|
@@ -107,6 +124,7 @@ end
107
124
 
108
125
  desc "Publish package files on RubyForge."
109
126
  task :publish_packages => [:verify_user, :verify_password, :package] do
127
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "vendor", "meta_project-0.4.15", "lib"))
110
128
  require 'meta_project'
111
129
  require 'rake/contrib/xforge'
112
130
  release_files = FileList[
data/examples/stubba.rb CHANGED
@@ -34,7 +34,7 @@ end
34
34
 
35
35
  require 'test/unit'
36
36
  require 'rubygems'
37
- require 'stubba'
37
+ require 'mocha'
38
38
 
39
39
  class OrderTest < Test::Unit::TestCase
40
40
 
@@ -1,12 +1,12 @@
1
1
  require 'mocha/mock'
2
2
 
3
- # Methods added to TestCase allowing creation of mock objects.
4
- #
5
- # Mocks created this way will have their expectations automatically verified at the end of the test.
6
- #
7
- # See Mocha::MockMethods for methods on mock objects.
8
- module Mocha
3
+ module Mocha # :nodoc:
9
4
 
5
+ # Methods added to TestCase allowing creation of traditional mock objects.
6
+ #
7
+ # Mocks created this way will have their expectations automatically verified at the end of the test.
8
+ #
9
+ # See Mock for methods on mock objects.
10
10
  module AutoVerify
11
11
 
12
12
  def mocks # :nodoc:
@@ -0,0 +1,22 @@
1
+ module Mocha
2
+
3
+ class Deprecation
4
+
5
+ class << self
6
+
7
+ attr_accessor :mode, :messages
8
+
9
+ def warning(message)
10
+ @messages << message
11
+ $stderr.puts "Mocha deprecation warning: #{message}" unless mode == :disabled
12
+ $stderr.puts caller.join("\n ") if mode == :debug
13
+ end
14
+
15
+ end
16
+
17
+ self.mode = :enabled
18
+ self.messages = []
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,17 @@
1
+ module Mocha # :nodoc:
2
+
3
+ class ExceptionRaiser # :nodoc:
4
+
5
+ def initialize(exception, message)
6
+ @exception, @message = exception, message
7
+ end
8
+
9
+ def evaluate
10
+ raise @exception, @exception.to_s if @exception == Interrupt
11
+ raise @exception, @message if @message
12
+ raise @exception
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -1,21 +1,18 @@
1
1
  require 'mocha/infinite_range'
2
2
  require 'mocha/pretty_parameters'
3
3
  require 'mocha/expectation_error'
4
+ require 'mocha/return_values'
5
+ require 'mocha/exception_raiser'
6
+ require 'mocha/yield_parameters'
7
+ require 'mocha/is_a'
4
8
 
5
- class Object
6
-
7
- alias_method :__is_a__, :is_a?
8
-
9
- end
10
-
11
- module Mocha
12
- # Methods on expectations returned from Mocha::MockMethods#expects and Mocha::MockMethods#stubs
9
+ module Mocha # :nodoc:
10
+
11
+ # Methods on expectations returned from Mock#expects, Mock#stubs, Object#expects and Object#stubs.
13
12
  class Expectation
14
13
 
15
14
  # :stopdoc:
16
15
 
17
- class InvalidExpectation < Exception; end
18
-
19
16
  class AlwaysEqual
20
17
  def ==(other)
21
18
  true
@@ -26,23 +23,26 @@ module Mocha
26
23
 
27
24
  def initialize(mock, method_name, backtrace = nil)
28
25
  @mock, @method_name = mock, method_name
29
- @count = 1
26
+ @expected_count = 1
30
27
  @parameters, @parameter_block = AlwaysEqual.new, nil
31
- @invoked, @return_value = 0, nil
28
+ @invoked_count, @return_values = 0, ReturnValues.new
32
29
  @backtrace = backtrace || caller
33
- @yield = nil
30
+ @yield_parameters = YieldParameters.new
34
31
  end
35
32
 
36
- def yield?
37
- @yield
38
- end
39
-
40
33
  def match?(method_name, *arguments)
34
+ return false unless @method_name == method_name
41
35
  if @parameter_block then
42
- @parameter_block.call(*arguments)
36
+ return false unless @parameter_block.call(*arguments)
37
+ else
38
+ return false unless (@parameters == arguments)
39
+ end
40
+ if @expected_count.is_a?(Range) then
41
+ return false unless @invoked_count < @expected_count.last
43
42
  else
44
- (@method_name == method_name) and (@parameters == arguments)
43
+ return false unless @invoked_count < @expected_count
45
44
  end
45
+ return true
46
46
  end
47
47
 
48
48
  # :startdoc:
@@ -54,34 +54,63 @@ module Mocha
54
54
  # +range+ can be specified as an exact integer or as a range of integers
55
55
  # object = mock()
56
56
  # object.expects(:expected_method).times(3)
57
- # 3.times { object.expected_method } # => verify succeeds
57
+ # 3.times { object.expected_method }
58
+ # # => verify succeeds
58
59
  #
59
60
  # object = mock()
60
61
  # object.expects(:expected_method).times(3)
61
- # 2.times { object.expected_method } # => verify fails
62
+ # 2.times { object.expected_method }
63
+ # # => verify fails
62
64
  #
63
65
  # object = mock()
64
66
  # object.expects(:expected_method).times(2..4)
65
- # 3.times { object.expected_method } # => verify succeeds
67
+ # 3.times { object.expected_method }
68
+ # # => verify succeeds
66
69
  #
67
70
  # object = mock()
68
71
  # object.expects(:expected_method).times(2..4)
69
- # object.expected_method # => verify fails
72
+ # object.expected_method
73
+ # # => verify fails
70
74
  def times(range)
71
- @count = range
75
+ @expected_count = range
76
+ self
77
+ end
78
+
79
+ # :call-seq: once() -> expectation
80
+ #
81
+ # Modifies expectation so that the expected method must be called exactly once.
82
+ # Note that this is the default behaviour for an expectation, but you may wish to use it for clarity/emphasis.
83
+ # object = mock()
84
+ # object.expects(:expected_method).once
85
+ # object.expected_method
86
+ # # => verify succeeds
87
+ #
88
+ # object = mock()
89
+ # object.expects(:expected_method).once
90
+ # object.expected_method
91
+ # object.expected_method
92
+ # # => verify fails
93
+ #
94
+ # object = mock()
95
+ # object.expects(:expected_method).once
96
+ # # => verify fails
97
+ def once()
98
+ times(1)
72
99
  self
73
100
  end
74
101
 
75
- # :call-seq: never -> expectation
102
+ # :call-seq: never() -> expectation
76
103
  #
77
104
  # Modifies expectation so that the expected method must never be called.
78
105
  # object = mock()
79
106
  # object.expects(:expected_method).never
80
- # object.expected_method # => verify fails
107
+ # object.expected_method
108
+ # # => verify fails
81
109
  #
82
110
  # object = mock()
83
111
  # object.expects(:expected_method).never
84
- # object.expected_method # => verify succeeds
112
+ # object.expected_method
113
+ # # => verify succeeds
85
114
  def never
86
115
  times(0)
87
116
  self
@@ -92,11 +121,13 @@ module Mocha
92
121
  # Modifies expectation so that the expected method must be called at least a +minimum_number_of_times+.
93
122
  # object = mock()
94
123
  # object.expects(:expected_method).at_least(2)
95
- # 3.times { object.expected_method } # => verify succeeds
124
+ # 3.times { object.expected_method }
125
+ # # => verify succeeds
96
126
  #
97
127
  # object = mock()
98
128
  # object.expects(:expected_method).at_least(2)
99
- # object.expected_method # => verify fails
129
+ # object.expected_method
130
+ # # => verify fails
100
131
  def at_least(minimum_number_of_times)
101
132
  times(Range.at_least(minimum_number_of_times))
102
133
  self
@@ -107,7 +138,8 @@ module Mocha
107
138
  # Modifies expectation so that the expected method must be called at least once.
108
139
  # object = mock()
109
140
  # object.expects(:expected_method).at_least_once
110
- # object.expected_method # => verify succeeds
141
+ # object.expected_method
142
+ # # => verify succeeds
111
143
  #
112
144
  # object = mock()
113
145
  # object.expects(:expected_method).at_least_once
@@ -122,11 +154,13 @@ module Mocha
122
154
  # Modifies expectation so that the expected method must be called at most a +maximum_number_of_times+.
123
155
  # object = mock()
124
156
  # object.expects(:expected_method).at_most(2)
125
- # 2.times { object.expected_method } # => verify succeeds
157
+ # 2.times { object.expected_method }
158
+ # # => verify succeeds
126
159
  #
127
160
  # object = mock()
128
161
  # object.expects(:expected_method).at_most(2)
129
- # 3.times { object.expected_method } # => verify fails
162
+ # 3.times { object.expected_method }
163
+ # # => verify fails
130
164
  def at_most(maximum_number_of_times)
131
165
  times(Range.at_most(maximum_number_of_times))
132
166
  self
@@ -137,11 +171,13 @@ module Mocha
137
171
  # Modifies expectation so that the expected method must be called at most once.
138
172
  # object = mock()
139
173
  # object.expects(:expected_method).at_most_once
140
- # object.expected_method # => verify succeeds
174
+ # object.expected_method
175
+ # # => verify succeeds
141
176
  #
142
177
  # object = mock()
143
178
  # object.expects(:expected_method).at_most_once
144
- # 2.times { object.expected_method } # => verify fails
179
+ # 2.times { object.expected_method }
180
+ # # => verify fails
145
181
  def at_most_once()
146
182
  at_most(1)
147
183
  self
@@ -152,20 +188,26 @@ module Mocha
152
188
  # Modifies expectation so that the expected method must be called with specified +arguments+.
153
189
  # object = mock()
154
190
  # object.expects(:expected_method).with(:param1, :param2)
155
- # object.expected_method(:param1, :param2) # => verify succeeds
191
+ # object.expected_method(:param1, :param2)
192
+ # # => verify succeeds
156
193
  #
157
194
  # object = mock()
158
195
  # object.expects(:expected_method).with(:param1, :param2)
159
- # object.expected_method(:param3) # => verify fails
196
+ # object.expected_method(:param3)
197
+ # # => verify fails
198
+ # May be used with parameter matchers in Mocha::ParameterMatchers.
199
+ #
160
200
  # If a +parameter_block+ is given, the block is called with the parameters passed to the expected method.
161
201
  # The expectation is matched if the block evaluates to +true+.
162
202
  # object = mock()
163
203
  # object.expects(:expected_method).with() { |value| value % 4 == 0 }
164
- # object.expected_method(16) # => verify succeeds
204
+ # object.expected_method(16)
205
+ # # => verify succeeds
165
206
  #
166
207
  # object = mock()
167
208
  # object.expects(:expected_method).with() { |value| value % 4 == 0 }
168
- # object.expected_method(17) # => verify fails
209
+ # object.expected_method(17)
210
+ # # => verify fails
169
211
  def with(*arguments, &parameter_block)
170
212
  @parameters, @parameter_block = arguments, parameter_block
171
213
  class << @parameters; def to_s; join(', '); end; end
@@ -180,12 +222,42 @@ module Mocha
180
222
  # yielded_value = nil
181
223
  # object.expected_method { |value| yielded_value = value }
182
224
  # yielded_value # => 'result'
225
+ # May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then.
226
+ # object = mock()
227
+ # object.stubs(:expected_method).yields(1).then.yields(2)
228
+ # yielded_values_from_first_invocation = []
229
+ # yielded_values_from_second_invocation = []
230
+ # object.expected_method { |value| yielded_values_from_first_invocation << value } # first invocation
231
+ # object.expected_method { |value| yielded_values_from_second_invocation << value } # second invocation
232
+ # yielded_values_from_first_invocation # => [1]
233
+ # yielded_values_from_second_invocation # => [2]
183
234
  def yields(*parameters)
184
- @yield = true
185
- @parameters_to_yield = parameters
235
+ @yield_parameters.add(*parameters)
186
236
  self
187
237
  end
188
-
238
+
239
+ # :call-seq: multiple_yields(*parameter_groups) -> expectation
240
+ #
241
+ # Modifies expectation so that when the expected method is called, it yields multiple times per invocation with the specified +parameter_groups+.
242
+ # object = mock()
243
+ # object.expects(:expected_method).multiple_yields(['result_1', 'result_2'], ['result_3'])
244
+ # yielded_values = []
245
+ # object.expected_method { |*values| yielded_values << values }
246
+ # yielded_values # => [['result_1', 'result_2'], ['result_3]]
247
+ # May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then.
248
+ # object = mock()
249
+ # object.stubs(:expected_method).multiple_yields([1, 2], [3]).then.multiple_yields([4], [5, 6])
250
+ # yielded_values_from_first_invocation = []
251
+ # yielded_values_from_second_invocation = []
252
+ # object.expected_method { |*values| yielded_values_from_first_invocation << values } # first invocation
253
+ # object.expected_method { |*values| yielded_values_from_second_invocation << values } # second invocation
254
+ # yielded_values_from_first_invocation # => [[1, 2], [3]]
255
+ # yielded_values_from_second_invocation # => [[4], [5, 6]]
256
+ def multiple_yields(*parameter_groups)
257
+ @yield_parameters.multiple_add(*parameter_groups)
258
+ self
259
+ end
260
+
189
261
  # :call-seq: returns(value) -> expectation
190
262
  # :call-seq: returns(*values) -> expectation
191
263
  #
@@ -199,13 +271,30 @@ module Mocha
199
271
  # object.stubs(:stubbed_method).returns(1, 2)
200
272
  # object.stubbed_method # => 1
201
273
  # object.stubbed_method # => 2
202
- # If +value+ is a Proc, then expected method will return result of calling Proc.
274
+ # May be called multiple times on the same expectation. Also see Expectation#then.
275
+ # object = mock()
276
+ # object.stubs(:expected_method).returns(1, 2).then.returns(3)
277
+ # object.expected_method # => 1
278
+ # object.expected_method # => 2
279
+ # object.expected_method # => 3
280
+ # May be called in conjunction with Expectation#raises on the same expectation.
281
+ # object = mock()
282
+ # object.stubs(:expected_method).returns(1, 2).then.raises(Exception)
283
+ # object.expected_method # => 1
284
+ # object.expected_method # => 2
285
+ # object.expected_method # => raises exception of class Exception1
286
+ # If +value+ is a +Proc+, then the expected method will return the result of calling <tt>Proc#call</tt>.
287
+ #
288
+ # This usage is _deprecated_.
289
+ # Use explicit multiple return values and/or multiple expectations instead.
290
+ #
291
+ # A +Proc+ instance will be treated the same as any other value in a future release.
203
292
  # object = mock()
204
293
  # object.stubs(:stubbed_method).returns(lambda { rand(100) })
205
294
  # object.stubbed_method # => 41
206
295
  # object.stubbed_method # => 77
207
296
  def returns(*values)
208
- @return_value = (values.size > 1) ? lambda { values.shift } : @return_value = values.first
297
+ @return_values += ReturnValues.build(*values)
209
298
  self
210
299
  end
211
300
 
@@ -215,23 +304,51 @@ module Mocha
215
304
  # object = mock()
216
305
  # object.expects(:expected_method).raises(Exception, 'message')
217
306
  # object.expected_method # => raises exception of class Exception and with message 'message'
307
+ # May be called multiple times on the same expectation. Also see Expectation#then.
308
+ # object = mock()
309
+ # object.stubs(:expected_method).raises(Exception1).then.raises(Exception2)
310
+ # object.expected_method # => raises exception of class Exception1
311
+ # object.expected_method # => raises exception of class Exception2
312
+ # May be called in conjunction with Expectation#returns on the same expectation.
313
+ # object = mock()
314
+ # object.stubs(:expected_method).raises(Exception).then.returns(2, 3)
315
+ # object.expected_method # => raises exception of class Exception1
316
+ # object.expected_method # => 2
317
+ # object.expected_method # => 3
218
318
  def raises(exception = RuntimeError, message = nil)
219
- @return_value = message ? lambda { raise exception, message } : lambda { raise exception }
319
+ @return_values += ReturnValues.new(ExceptionRaiser.new(exception, message))
220
320
  self
221
321
  end
222
322
 
323
+ # :call-seq: then() -> expectation
324
+ #
325
+ # Syntactic sugar to improve readability. Has no effect on state of the expectation.
326
+ # object = mock()
327
+ # object.stubs(:expected_method).returns(1, 2).then.raises(Exception).then.returns(4)
328
+ # object.expected_method # => 1
329
+ # object.expected_method # => 2
330
+ # object.expected_method # => raises exception of class Exception
331
+ # object.expected_method # => 4
332
+ def then
333
+ self
334
+ end
335
+
223
336
  # :stopdoc:
224
337
 
225
338
  def invoke
226
- @invoked += 1
227
- yield(*@parameters_to_yield) if yield? and block_given?
228
- @return_value.__is_a__(Proc) ? @return_value.call : @return_value
339
+ @invoked_count += 1
340
+ if block_given? then
341
+ @yield_parameters.next_invocation.each do |yield_parameters|
342
+ yield(*yield_parameters)
343
+ end
344
+ end
345
+ @return_values.next
229
346
  end
230
347
 
231
348
  def verify
232
349
  yield(self) if block_given?
233
- unless (@count === @invoked) then
234
- error = ExpectationError.new(error_message(@count, @invoked))
350
+ unless (@expected_count === @invoked_count) then
351
+ error = ExpectationError.new(error_message(@expected_count, @invoked_count))
235
352
  error.set_backtrace(filtered_backtrace)
236
353
  raise error
237
354
  end
@@ -251,45 +368,11 @@ module Mocha
251
368
  end
252
369
 
253
370
  def error_message(expected_count, actual_count)
254
- "#{@mock.mocha_inspect}.#{method_signature} - expected calls: #{expected_count}, actual calls: #{actual_count}"
371
+ "#{@mock.mocha_inspect}.#{method_signature} - expected calls: #{expected_count.mocha_inspect}, actual calls: #{actual_count}"
255
372
  end
256
373
 
257
374
  # :startdoc:
258
375
 
259
376
  end
260
377
 
261
- # :stopdoc:
262
-
263
- class Stub < Expectation
264
-
265
- def verify
266
- true
267
- end
268
-
269
- end
270
-
271
- class MissingExpectation < Expectation
272
-
273
- def initialize(mock, method_name)
274
- super
275
- @invoked = true
276
- end
277
-
278
- def verify
279
- msg = error_message(0, 1)
280
- similar_expectations_list = similar_expectations.collect { |expectation| expectation.method_signature }.join("\n")
281
- msg << "\nSimilar expectations:\n#{similar_expectations_list}" unless similar_expectations.empty?
282
- error = ExpectationError.new(msg)
283
- error.set_backtrace(filtered_backtrace)
284
- raise error if @invoked
285
- end
286
-
287
- def similar_expectations
288
- @mock.expectations.select { |expectation| expectation.method_name == self.method_name }
289
- end
290
-
291
- end
292
-
293
- # :startdoc:
294
-
295
378
  end