mocha 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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