rspec 1.2.9 → 1.3.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 (67) hide show
  1. data/History.rdoc +34 -1
  2. data/License.txt +1 -1
  3. data/Manifest.txt +11 -4
  4. data/README.rdoc +2 -3
  5. data/Rakefile +17 -13
  6. data/Upgrade.rdoc +63 -2
  7. data/features/formatters/nested_formatter.feature +32 -0
  8. data/features/interop/cucumber_stubs_dont_leak.feature +11 -0
  9. data/features/matchers/define_matcher_with_fluent_interface.feature +21 -0
  10. data/features/matchers/define_wrapped_matcher.feature +28 -1
  11. data/features/matchers/match_unless_raises.feature +60 -0
  12. data/features/matchers/match_unless_raises_unexpected_error.feature +39 -0
  13. data/features/mocks/block_local_expectations.feature +62 -0
  14. data/features/step_definitions/running_rspec_steps.rb +9 -0
  15. data/features/step_definitions/stubbing_steps.rb +16 -0
  16. data/features/support/env.rb +1 -0
  17. data/features/support/matchers/smart_match.rb +23 -4
  18. data/geminstaller.yml +28 -0
  19. data/lib/autotest/rspec.rb +14 -7
  20. data/lib/spec/dsl/main.rb +1 -1
  21. data/lib/spec/example/example_methods.rb +4 -0
  22. data/lib/spec/{matchers/extensions → extensions}/instance_exec.rb +0 -0
  23. data/lib/spec/interop/test.rb +1 -1
  24. data/lib/spec/matchers.rb +21 -2
  25. data/lib/spec/matchers/be.rb +167 -128
  26. data/lib/spec/matchers/has.rb +3 -3
  27. data/lib/spec/matchers/have.rb +1 -0
  28. data/lib/spec/matchers/matcher.rb +55 -10
  29. data/lib/spec/matchers/method_missing.rb +2 -2
  30. data/lib/spec/matchers/raise_exception.rb +131 -0
  31. data/lib/spec/matchers/throw_symbol.rb +16 -20
  32. data/lib/spec/mocks/message_expectation.rb +63 -48
  33. data/lib/spec/mocks/methods.rb +13 -8
  34. data/lib/spec/mocks/proxy.rb +43 -22
  35. data/lib/spec/runner/differs/default.rb +1 -1
  36. data/lib/spec/runner/drb_command_line.rb +8 -2
  37. data/lib/spec/runner/example_group_runner.rb +1 -2
  38. data/lib/spec/runner/formatter/nested_text_formatter.rb +6 -3
  39. data/lib/spec/runner/option_parser.rb +2 -0
  40. data/lib/spec/runner/options.rb +6 -1
  41. data/lib/spec/stubs/cucumber.rb +2 -2
  42. data/lib/spec/version.rb +2 -2
  43. data/spec/autotest/autotest_helper.rb +1 -1
  44. data/spec/autotest/discover_spec.rb +2 -2
  45. data/spec/autotest/failed_results_re_spec.rb +2 -2
  46. data/spec/autotest/rspec_spec.rb +21 -6
  47. data/spec/spec/example/example_group_methods_spec.rb +2 -1
  48. data/spec/spec/interop/test/unit/spec_spec.rb +7 -7
  49. data/spec/spec/interop/test/unit/testcase_spec.rb +7 -7
  50. data/spec/spec/interop/test/unit/testsuite_adapter_spec.rb +1 -1
  51. data/spec/spec/matchers/be_spec.rb +159 -10
  52. data/spec/spec/matchers/has_spec.rb +109 -0
  53. data/spec/spec/matchers/matcher_spec.rb +70 -9
  54. data/spec/spec/matchers/raise_exception_spec.rb +345 -0
  55. data/spec/spec/matchers/throw_symbol_spec.rb +83 -58
  56. data/spec/spec/mocks/and_yield_spec.rb +117 -0
  57. data/spec/spec/mocks/mock_spec.rb +2 -2
  58. data/spec/spec/runner/command_line_spec.rb +26 -5
  59. data/spec/spec/runner/drb_command_line_spec.rb +39 -0
  60. data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +35 -11
  61. data/spec/spec/runner/option_parser_spec.rb +12 -6
  62. data/spec/spec/runner/options_spec.rb +7 -0
  63. data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +23 -5
  64. metadata +17 -10
  65. data/lib/spec/matchers/raise_error.rb +0 -129
  66. data/spec/spec/matchers/matcher_methods_spec.rb +0 -63
  67. data/spec/spec/matchers/raise_error_spec.rb +0 -333
@@ -3,12 +3,12 @@ module Spec
3
3
 
4
4
  class Has
5
5
 
6
- def initialize(expected, *args)
7
- @expected, @args = expected, args
6
+ def initialize(expected, *args, &block)
7
+ @expected, @args, @block = expected, args, block
8
8
  end
9
9
 
10
10
  def matches?(actual)
11
- actual.__send__(predicate(@expected), *@args)
11
+ actual.__send__(predicate(@expected), *@args, &@block)
12
12
  end
13
13
 
14
14
  def failure_message_for_should
@@ -5,6 +5,7 @@ module Spec
5
5
  @expected = (expected == :no ? 0 : expected)
6
6
  @relativity = relativity
7
7
  @actual = nil
8
+ @plural_collection_name = nil
8
9
  end
9
10
 
10
11
  def relativities
@@ -12,6 +12,7 @@ module Spec
12
12
  @expected = expected
13
13
  @actual = nil
14
14
  @diffable = false
15
+ @expected_exception = nil
15
16
  @messages = {
16
17
  :description => lambda {"#{name_to_sentence}#{expected_to_sentence}"},
17
18
  :failure_message_for_should => lambda {|actual| "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"},
@@ -22,33 +23,70 @@ module Spec
22
23
  end
23
24
  end
24
25
 
26
+ #Used internally by objects returns by +should+ and +should_not+.
25
27
  def matches?(actual)
26
- instance_exec(@actual = actual, &@match_block)
28
+ @actual = actual
29
+ if @expected_exception
30
+ begin
31
+ instance_exec(actual, &@match_block)
32
+ true
33
+ rescue @expected_exception
34
+ false
35
+ end
36
+ else
37
+ begin
38
+ instance_exec(actual, &@match_block)
39
+ rescue Spec::Expectations::ExpectationNotMetError
40
+ false
41
+ end
42
+ end
27
43
  end
28
44
 
29
- def description(&block)
30
- cache_or_call_cached(:description, &block)
45
+ # See Spec::Matchers
46
+ def match(&block)
47
+ @match_block = block
31
48
  end
32
49
 
50
+ # See Spec::Matchers
51
+ def match_unless_raises(exception=Exception, &block)
52
+ @expected_exception = exception
53
+ match(&block)
54
+ end
55
+
56
+ # See Spec::Matchers
33
57
  def failure_message_for_should(&block)
34
- cache_or_call_cached(:failure_message_for_should, actual, &block)
58
+ cache_or_call_cached(:failure_message_for_should, &block)
35
59
  end
36
60
 
61
+ # See Spec::Matchers
37
62
  def failure_message_for_should_not(&block)
38
- cache_or_call_cached(:failure_message_for_should_not, actual, &block)
63
+ cache_or_call_cached(:failure_message_for_should_not, &block)
39
64
  end
40
65
 
41
- def match(&block)
42
- @match_block = block
66
+ # See Spec::Matchers
67
+ def description(&block)
68
+ cache_or_call_cached(:description, &block)
43
69
  end
44
70
 
71
+ #Used internally by objects returns by +should+ and +should_not+.
45
72
  def diffable?
46
73
  @diffable
47
74
  end
48
75
 
76
+ # See Spec::Matchers
49
77
  def diffable
50
78
  @diffable = true
51
79
  end
80
+
81
+ # See Spec::Matchers
82
+ def chain(method, &block)
83
+ self.class.class_eval do
84
+ define_method method do |*args|
85
+ block.call(*args)
86
+ self
87
+ end
88
+ end
89
+ end
52
90
 
53
91
  private
54
92
 
@@ -69,9 +107,16 @@ module Spec
69
107
  (private_methods - orig_private_methods).each {|m| st.__send__ :public, m}
70
108
  end
71
109
 
72
- def cache_or_call_cached(key, actual=nil, &block)
73
- block ? @messages[key] = block :
74
- actual.nil? ? @messages[key].call : @messages[key].call(actual)
110
+ def cache_or_call_cached(key, &block)
111
+ block ? cache(key, &block) : call_cached(key)
112
+ end
113
+
114
+ def cache(key, &block)
115
+ @messages[key] = block
116
+ end
117
+
118
+ def call_cached(key)
119
+ @messages[key].arity == 1 ? @messages[key].call(@actual) : @messages[key].call
75
120
  end
76
121
 
77
122
  def name_to_sentence
@@ -1,8 +1,8 @@
1
1
  module Spec
2
2
  module Matchers
3
3
  def method_missing(sym, *args, &block) # :nodoc:
4
- return Matchers::Be.new(sym, *args) if sym.to_s =~ /^be_/
5
- return Matchers::Has.new(sym, *args) if sym.to_s =~ /^have_/
4
+ return Matchers::BePredicate.new(sym, *args, &block) if sym.to_s =~ /^be_/
5
+ return Matchers::Has.new(sym, *args, &block) if sym.to_s =~ /^have_/
6
6
  super
7
7
  end
8
8
  end
@@ -0,0 +1,131 @@
1
+ module Spec
2
+ module Matchers
3
+ class RaiseException #:nodoc:
4
+ def initialize(expected_exception_or_message=Exception, expected_message=nil, &block)
5
+ @block = block
6
+ @actual_exception = nil
7
+ case expected_exception_or_message
8
+ when String, Regexp
9
+ @expected_exception, @expected_message = Exception, expected_exception_or_message
10
+ else
11
+ @expected_exception, @expected_message = expected_exception_or_message, expected_message
12
+ end
13
+ end
14
+
15
+ def matches?(given_proc)
16
+ @raised_expected_exception = false
17
+ @with_expected_message = false
18
+ @eval_block = false
19
+ @eval_block_passed = false
20
+ begin
21
+ given_proc.call
22
+ rescue @expected_exception => @actual_exception
23
+ @raised_expected_exception = true
24
+ @with_expected_message = verify_message
25
+ rescue Exception => @actual_exception
26
+ # This clause should be empty, but rcov will not report it as covered
27
+ # unless something (anything) is executed within the clause
28
+ rcov_exception_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
29
+ end
30
+
31
+ unless negative_expectation?
32
+ eval_block if @raised_expected_exception && @with_expected_message && @block
33
+ end
34
+
35
+ (@raised_expected_exception & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
36
+ end
37
+
38
+ def eval_block
39
+ @eval_block = true
40
+ begin
41
+ @block[@actual_exception]
42
+ @eval_block_passed = true
43
+ rescue Exception => err
44
+ @actual_exception = err
45
+ end
46
+ end
47
+
48
+ def verify_message
49
+ case @expected_message
50
+ when nil
51
+ true
52
+ when Regexp
53
+ @expected_message =~ @actual_exception.message
54
+ else
55
+ @expected_message == @actual_exception.message
56
+ end
57
+ end
58
+
59
+ def failure_message_for_should
60
+ @eval_block ? @actual_exception.message : "expected #{expected_exception}#{given_exception}"
61
+ end
62
+
63
+ def failure_message_for_should_not
64
+ "expected no #{expected_exception}#{given_exception}"
65
+ end
66
+
67
+ def description
68
+ "raise #{expected_exception}"
69
+ end
70
+
71
+ private
72
+ def expected_exception
73
+ case @expected_message
74
+ when nil
75
+ @expected_exception
76
+ when Regexp
77
+ "#{@expected_exception} with message matching #{@expected_message.inspect}"
78
+ else
79
+ "#{@expected_exception} with #{@expected_message.inspect}"
80
+ end
81
+ end
82
+
83
+ def given_exception
84
+ @actual_exception.nil? ? " but nothing was raised" : ", got #{@actual_exception.inspect}"
85
+ end
86
+
87
+ def negative_expectation?
88
+ # YES - I'm a bad person... help me find a better way - ryand
89
+ caller.first(3).find { |s| s =~ /should_not/ }
90
+ end
91
+ end
92
+
93
+ # :call-seq:
94
+ # should raise_exception()
95
+ # should raise_exception(NamedError)
96
+ # should raise_exception(NamedError, String)
97
+ # should raise_exception(NamedError, Regexp)
98
+ # should raise_exception() { |exception| ... }
99
+ # should raise_exception(NamedError) { |exception| ... }
100
+ # should raise_exception(NamedError, String) { |exception| ... }
101
+ # should raise_exception(NamedError, Regexp) { |exception| ... }
102
+ # should_not raise_exception()
103
+ # should_not raise_exception(NamedError)
104
+ # should_not raise_exception(NamedError, String)
105
+ # should_not raise_exception(NamedError, Regexp)
106
+ #
107
+ # With no args, matches if any exception is raised.
108
+ # With a named exception, matches only if that specific exception is raised.
109
+ # With a named exception and messsage specified as a String, matches only if both match.
110
+ # With a named exception and messsage specified as a Regexp, matches only if both match.
111
+ # Pass an optional block to perform extra verifications on the exception matched
112
+ #
113
+ # == Examples
114
+ #
115
+ # lambda { do_something_risky }.should raise_exception
116
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError)
117
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError) { |exception| exception.data.should == 42 }
118
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError, "that was too risky")
119
+ # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError, /oo ri/)
120
+ #
121
+ # lambda { do_something_risky }.should_not raise_exception
122
+ # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError)
123
+ # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError, "that was too risky")
124
+ # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError, /oo ri/)
125
+ def raise_exception(exception=Exception, message=nil, &block)
126
+ Matchers::RaiseException.new(exception, message, &block)
127
+ end
128
+
129
+ alias_method :raise_error, :raise_exception
130
+ end
131
+ end
@@ -1,13 +1,13 @@
1
1
  module Spec
2
2
  module Matchers
3
-
3
+
4
4
  class ThrowSymbol #:nodoc:
5
5
  def initialize(expected_symbol = nil, expected_arg=nil)
6
6
  @expected_symbol = expected_symbol
7
7
  @expected_arg = expected_arg
8
8
  @caught_symbol = @caught_arg = nil
9
9
  end
10
-
10
+
11
11
  def matches?(given_proc)
12
12
  begin
13
13
  if @expected_symbol.nil?
@@ -27,17 +27,13 @@ module Spec
27
27
  rescue NameError, ArgumentError => e
28
28
  raise e unless e.message =~ /uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/
29
29
  @caught_symbol = $2.to_sym
30
-
31
- ensure
32
- if @expected_symbol.nil?
33
- return !@caught_symbol.nil?
34
- else
35
- if @expected_arg.nil?
36
- return @caught_symbol == @expected_symbol
37
- else
38
- return (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg)
39
- end
40
- end
30
+ end
31
+ if @expected_symbol.nil?
32
+ !@caught_symbol.nil?
33
+ elsif @expected_arg.nil?
34
+ @caught_symbol == @expected_symbol
35
+ else
36
+ (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg)
41
37
  end
42
38
  end
43
39
 
@@ -48,7 +44,7 @@ module Spec
48
44
  "expected #{expected} but nothing was thrown"
49
45
  end
50
46
  end
51
-
47
+
52
48
  def failure_message_for_should_not
53
49
  if @expected_symbol
54
50
  "expected #{expected} not to be thrown"
@@ -56,23 +52,23 @@ module Spec
56
52
  "expected no Symbol, got :#{@caught_symbol}"
57
53
  end
58
54
  end
59
-
55
+
60
56
  def description
61
57
  "throw #{expected}"
62
58
  end
63
-
59
+
64
60
  private
65
-
61
+
66
62
  def expected
67
63
  @expected_symbol.nil? ? "a Symbol" : "#{@expected_symbol.inspect}#{args}"
68
64
  end
69
-
65
+
70
66
  def args
71
67
  @expected_arg.nil? ? "" : " with #{@expected_arg.inspect}"
72
68
  end
73
-
69
+
74
70
  end
75
-
71
+
76
72
  # :call-seq:
77
73
  # should throw_symbol()
78
74
  # should throw_symbol(:sym)
@@ -7,7 +7,7 @@ module Spec
7
7
  protected :expected_received_count=, :method_block=, :expected_from=
8
8
  attr_accessor :error_generator
9
9
  protected :error_generator, :error_generator=
10
-
10
+
11
11
  def initialize(error_generator, expectation_ordering, expected_from, sym, method_block, expected_received_count=1, opts={}, &implementation)
12
12
  @error_generator = error_generator
13
13
  @error_generator.opts = opts
@@ -27,8 +27,9 @@ module Spec
27
27
  @failed_fast = nil
28
28
  @args_to_yield_were_cloned = false
29
29
  @return_block = implementation
30
+ @eval_context = nil
30
31
  end
31
-
32
+
32
33
  def build_child(expected_from, method_block, expected_received_count, opts={})
33
34
  child = clone
34
35
  child.expected_from = expected_from
@@ -41,7 +42,7 @@ module Spec
41
42
  child.clone_args_to_yield @args_to_yield
42
43
  child
43
44
  end
44
-
45
+
45
46
  def expected_args
46
47
  @args_expectation.args
47
48
  end
@@ -59,7 +60,7 @@ module Spec
59
60
  end
60
61
  @return_block = block_given? ? return_block : lambda { value }
61
62
  end
62
-
63
+
63
64
  # :call-seq:
64
65
  # and_raise()
65
66
  # and_raise(Exception) #any exception class
@@ -74,47 +75,53 @@ module Spec
74
75
  def and_raise(exception=Exception)
75
76
  @exception_to_raise = exception
76
77
  end
77
-
78
+
78
79
  def and_throw(symbol)
79
80
  @symbol_to_throw = symbol
80
81
  end
81
-
82
- def and_yield(*args)
82
+
83
+ def and_yield(*args, &block)
83
84
  if @args_to_yield_were_cloned
84
85
  @args_to_yield.clear
85
86
  @args_to_yield_were_cloned = false
86
87
  end
87
-
88
+
89
+ if block
90
+ require 'spec/extensions/instance_exec'
91
+ @eval_context = Object.new
92
+ @eval_context.extend Spec::Matchers::InstanceExec
93
+ yield @eval_context
94
+ end
88
95
  @args_to_yield << args
89
96
  self
90
97
  end
91
-
98
+
92
99
  def matches(sym, args)
93
100
  @sym == sym and @args_expectation.args_match?(args)
94
101
  end
95
-
102
+
96
103
  def invoke(*args, &block)
97
104
  if @expected_received_count == 0
98
105
  @failed_fast = true
99
106
  @actual_received_count += 1
100
107
  @error_generator.raise_expectation_error @sym, @expected_received_count, @actual_received_count, *args
101
108
  end
102
-
109
+
103
110
  @order_group.handle_order_constraint self
104
111
 
105
112
  begin
106
113
  Kernel::raise @exception_to_raise unless @exception_to_raise.nil?
107
114
  Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil?
108
-
109
-
115
+
116
+
110
117
  if !@method_block.nil?
111
118
  default_return_val = invoke_method_block(*args)
112
- elsif @args_to_yield.size > 0
119
+ elsif @args_to_yield.size > 0 || @eval_context
113
120
  default_return_val = invoke_with_yield(&block)
114
121
  else
115
122
  default_return_val = nil
116
123
  end
117
-
124
+
118
125
  if @consecutive
119
126
  return invoke_consecutive_return_block(*args, &block)
120
127
  elsif @return_block
@@ -131,7 +138,7 @@ module Spec
131
138
  @expected_received_count != :any && @expected_received_count > 0 &&
132
139
  @actual_received_count >= @expected_received_count
133
140
  end
134
-
141
+
135
142
  def invoke_return_block(*args, &block)
136
143
  args << block unless block.nil?
137
144
  # Ruby 1.9 - when we set @return_block to return values
@@ -139,7 +146,7 @@ module Spec
139
146
  # a "wrong number of arguments" error
140
147
  @return_block.arity == 0 ? @return_block.call : @return_block.call(*args)
141
148
  end
142
-
149
+
143
150
  protected
144
151
 
145
152
  def invoke_method_block(*args)
@@ -149,7 +156,7 @@ module Spec
149
156
  @error_generator.raise_block_failed_error @sym, detail.message
150
157
  end
151
158
  end
152
-
159
+
153
160
  def invoke_with_yield(&block)
154
161
  if block.nil?
155
162
  @error_generator.raise_missing_block_error @args_to_yield
@@ -159,67 +166,75 @@ module Spec
159
166
  if block.arity > -1 && args_to_yield_this_time.length != block.arity
160
167
  @error_generator.raise_wrong_arity_error args_to_yield_this_time, block.arity
161
168
  end
162
- value = block.call(*args_to_yield_this_time)
169
+ value = eval_block(*args_to_yield_this_time, &block)
163
170
  end
164
171
  value
165
172
  end
166
-
173
+
174
+ def eval_block(*args, &block)
175
+ if @eval_context
176
+ @eval_context.instance_exec(*args, &block)
177
+ else
178
+ block.call(*args)
179
+ end
180
+ end
181
+
167
182
  def invoke_consecutive_return_block(*args, &block)
168
183
  value = invoke_return_block(*args, &block)
169
184
  index = [@actual_received_count, value.size-1].min
170
185
  value[index]
171
186
  end
172
-
187
+
173
188
  def clone_args_to_yield(args)
174
189
  @args_to_yield = args.clone
175
190
  @args_to_yield_were_cloned = true
176
191
  end
177
-
192
+
178
193
  def failed_fast?
179
194
  @failed_fast
180
195
  end
181
196
  end
182
-
197
+
183
198
  class MessageExpectation < BaseExpectation
184
199
 
185
200
  def matches_name?(sym)
186
201
  @sym == sym
187
202
  end
188
-
203
+
189
204
  def matches_name_but_not_args(sym, args)
190
205
  matches_name?(sym) and not @args_expectation.args_match?(args)
191
206
  end
192
-
207
+
193
208
  def verify_messages_received
194
209
  return if expected_messages_received? || failed_fast?
195
-
210
+
196
211
  generate_error
197
212
  rescue Spec::Mocks::MockExpectationError => error
198
213
  error.backtrace.insert(0, @expected_from)
199
214
  Kernel::raise error
200
215
  end
201
-
216
+
202
217
  def expected_messages_received?
203
218
  ignoring_args? || matches_exact_count? ||
204
219
  matches_at_least_count? || matches_at_most_count?
205
220
  end
206
-
221
+
207
222
  def ignoring_args?
208
223
  @expected_received_count == :any
209
224
  end
210
-
225
+
211
226
  def matches_at_least_count?
212
227
  @at_least && @actual_received_count >= @expected_received_count
213
228
  end
214
-
229
+
215
230
  def matches_at_most_count?
216
231
  @at_most && @actual_received_count <= @expected_received_count
217
232
  end
218
-
233
+
219
234
  def matches_exact_count?
220
235
  @expected_received_count == @actual_received_count
221
236
  end
222
-
237
+
223
238
  def similar_messages
224
239
  @similar_messages ||= []
225
240
  end
@@ -227,7 +242,7 @@ module Spec
227
242
  def advise(args, block)
228
243
  similar_messages << args
229
244
  end
230
-
245
+
231
246
  def generate_error
232
247
  if similar_messages.empty?
233
248
  @error_generator.raise_expectation_error(@sym, @expected_received_count, @actual_received_count, *@args_expectation.args)
@@ -240,17 +255,17 @@ module Spec
240
255
  @args_expectation = ArgumentExpectation.new(args, &block)
241
256
  self
242
257
  end
243
-
258
+
244
259
  def exactly(n)
245
260
  set_expected_received_count :exactly, n
246
261
  self
247
262
  end
248
-
263
+
249
264
  def at_least(n)
250
265
  set_expected_received_count :at_least, n
251
266
  self
252
267
  end
253
-
268
+
254
269
  def at_most(n)
255
270
  set_expected_received_count :at_most, n
256
271
  self
@@ -260,41 +275,41 @@ module Spec
260
275
  @method_block = block if block
261
276
  self
262
277
  end
263
-
278
+
264
279
  def any_number_of_times(&block)
265
280
  @method_block = block if block
266
281
  @expected_received_count = :any
267
282
  self
268
283
  end
269
-
284
+
270
285
  def never
271
286
  @expected_received_count = 0
272
287
  self
273
288
  end
274
-
289
+
275
290
  def once(&block)
276
291
  @method_block = block if block
277
292
  @expected_received_count = 1
278
293
  self
279
294
  end
280
-
295
+
281
296
  def twice(&block)
282
297
  @method_block = block if block
283
298
  @expected_received_count = 2
284
299
  self
285
300
  end
286
-
301
+
287
302
  def ordered(&block)
288
303
  @method_block = block if block
289
304
  @order_group.register(self)
290
305
  @ordered = true
291
306
  self
292
307
  end
293
-
308
+
294
309
  def negative_expectation_for?(sym)
295
310
  return false
296
311
  end
297
-
312
+
298
313
  protected
299
314
  def set_expected_received_count(relativity, n)
300
315
  @at_least = (relativity == :at_least)
@@ -308,22 +323,22 @@ module Spec
308
323
  2
309
324
  end
310
325
  end
311
-
326
+
312
327
  def clear_actual_received_count!
313
328
  @actual_received_count = 0
314
329
  end
315
-
330
+
316
331
  end
317
-
332
+
318
333
  class NegativeMessageExpectation < MessageExpectation
319
334
  def initialize(message, expectation_ordering, expected_from, sym, method_block)
320
335
  super(message, expectation_ordering, expected_from, sym, method_block, 0)
321
336
  end
322
-
337
+
323
338
  def negative_expectation_for?(sym)
324
339
  return @sym == sym
325
340
  end
326
341
  end
327
-
342
+
328
343
  end
329
344
  end