Class: Mocha::Expectation
Overview
Methods on expectations returned from Mock#expects, Mock#stubs, Object#expects and Object#stubs.
Instance Attribute Summary collapse
-
#backtrace ⇒ Object
readonly
:stopdoc:.
Instance Method Summary collapse
- #add_in_sequence_ordering_constraint(sequence) ⇒ Object
- #add_ordering_constraint(ordering_constraint) ⇒ Object
- #add_side_effect(side_effect) ⇒ Object
-
#at_least(minimum_number_of_times) ⇒ Object
:call-seq: at_least(minimum_number_of_times) -> expectation.
-
#at_least_once ⇒ Object
:call-seq: at_least_once() -> expectation.
-
#at_most(maximum_number_of_times) ⇒ Object
:call-seq: at_most(maximum_number_of_times) -> expectation.
-
#at_most_once ⇒ Object
:call-seq: at_most_once() -> expectation.
- #in_correct_order? ⇒ Boolean
-
#in_sequence(*sequences) ⇒ Object
:call-seq: in_sequence(*sequences) -> expectation.
-
#initialize(mock, expected_method_name, backtrace = nil) ⇒ Expectation
constructor
A new instance of Expectation.
- #invocations_allowed? ⇒ Boolean
- #invoke ⇒ Object
- #match?(actual_method_name, *actual_parameters) ⇒ Boolean
- #matches_method?(method_name) ⇒ Boolean
- #method_signature ⇒ Object
- #mocha_inspect ⇒ Object
-
#multiple_yields(*parameter_groups) ⇒ Object
:call-seq: multiple_yields(*parameter_groups) -> expectation.
-
#never ⇒ Object
:call-seq: never() -> expectation.
-
#once ⇒ Object
:call-seq: once() -> expectation.
- #perform_side_effects ⇒ Object
-
#raises(exception = RuntimeError, message = nil) ⇒ Object
:call-seq: raises(exception = RuntimeError, message = nil) -> expectation.
-
#returns(*values) ⇒ Object
:call-seq: returns(value) -> expectation returns(*values) -> expectation.
- #satisfied? ⇒ Boolean
-
#then(*parameters) ⇒ Object
:call-seq: then() -> expectation then(state_machine.is(state)) -> expectation.
-
#times(range) ⇒ Object
:call-seq: times(range) -> expectation.
-
#twice ⇒ Object
:call-seq: twice() -> expectation.
- #used? ⇒ Boolean
- #verified?(assertion_counter = nil) ⇒ Boolean
-
#when(state_predicate) ⇒ Object
:call-seq: when(state_machine.is(state)) -> exception.
-
#with(*expected_parameters, &matching_block) ⇒ Object
:call-seq: with(*expected_parameters, &matching_block) -> expectation.
-
#yields(*parameters) ⇒ Object
:call-seq: yields(*parameters) -> expectation.
Constructor Details
#initialize(mock, expected_method_name, backtrace = nil) ⇒ Expectation
Returns a new instance of Expectation.
389 390 391 392 393 394 395 396 397 398 399 |
# File 'lib/mocha/expectation.rb', line 389 def initialize(mock, expected_method_name, backtrace = nil) @mock = mock @method_matcher = MethodMatcher.new(expected_method_name.to_sym) @parameters_matcher = ParametersMatcher.new @ordering_constraints = [] @side_effects = [] @cardinality, @invocation_count = Cardinality.exactly(1), 0 @return_values = ReturnValues.new @yield_parameters = YieldParameters.new @backtrace = backtrace || caller end |
Instance Attribute Details
#backtrace ⇒ Object (readonly)
:stopdoc:
387 388 389 |
# File 'lib/mocha/expectation.rb', line 387 def backtrace @backtrace end |
Instance Method Details
#add_in_sequence_ordering_constraint(sequence) ⇒ Object
405 406 407 |
# File 'lib/mocha/expectation.rb', line 405 def add_in_sequence_ordering_constraint(sequence) sequence.constrain_as_next_in_sequence(self) end |
#add_ordering_constraint(ordering_constraint) ⇒ Object
401 402 403 |
# File 'lib/mocha/expectation.rb', line 401 def add_ordering_constraint(ordering_constraint) @ordering_constraints << ordering_constraint end |
#add_side_effect(side_effect) ⇒ Object
409 410 411 |
# File 'lib/mocha/expectation.rb', line 409 def add_side_effect(side_effect) @side_effects << side_effect end |
#at_least(minimum_number_of_times) ⇒ Object
:call-seq: at_least(minimum_number_of_times) -> expectation
Modifies expectation so that the expected method must be called at least a minimum_number_of_times
.
object = mock()
object.expects(:expected_method).at_least(2)
3.times { object.expected_method }
# => verify succeeds
object = mock()
object.expects(:expected_method).at_least(2)
object.expected_method
# => verify fails
122 123 124 125 |
# File 'lib/mocha/expectation.rb', line 122 def at_least(minimum_number_of_times) @cardinality = Cardinality.at_least(minimum_number_of_times) self end |
#at_least_once ⇒ Object
:call-seq: at_least_once() -> expectation
Modifies expectation so that the expected method must be called at least once.
object = mock()
object.expects(:expected_method).at_least_once
object.expected_method
# => verify succeeds
object = mock()
object.expects(:expected_method).at_least_once
# => verify fails
138 139 140 141 |
# File 'lib/mocha/expectation.rb', line 138 def at_least_once at_least(1) self end |
#at_most(maximum_number_of_times) ⇒ Object
:call-seq: at_most(maximum_number_of_times) -> expectation
Modifies expectation so that the expected method must be called at most a maximum_number_of_times
.
object = mock()
object.expects(:expected_method).at_most(2)
2.times { object.expected_method }
# => verify succeeds
object = mock()
object.expects(:expected_method).at_most(2)
3.times { object.expected_method }
# => verify fails
155 156 157 158 |
# File 'lib/mocha/expectation.rb', line 155 def at_most(maximum_number_of_times) @cardinality = Cardinality.at_most(maximum_number_of_times) self end |
#at_most_once ⇒ Object
:call-seq: at_most_once() -> expectation
Modifies expectation so that the expected method must be called at most once.
object = mock()
object.expects(:expected_method).at_most_once
object.expected_method
# => verify succeeds
object = mock()
object.expects(:expected_method).at_most_once
2.times { object.expected_method }
# => verify fails
172 173 174 175 |
# File 'lib/mocha/expectation.rb', line 172 def at_most_once() at_most(1) self end |
#in_correct_order? ⇒ Boolean
417 418 419 |
# File 'lib/mocha/expectation.rb', line 417 def in_correct_order? @ordering_constraints.all? { |ordering_constraint| ordering_constraint.allows_invocation_now? } end |
#in_sequence(*sequences) ⇒ Object
:call-seq: in_sequence(*sequences) -> expectation
Constrains this expectation so that it must be invoked at the current point in the sequence.
To expect a sequence of invocations, write the expectations in order and add the in_sequence(sequence) clause to each one.
Expectations in a sequence can have any invocation count.
If an expectation in a sequence is stubbed, rather than expected, it can be skipped in the sequence.
See also API#sequence.
breakfast = sequence('breakfast')
egg = mock('egg')
egg.expects(:crack).in_sequence(breakfast)
egg.expects(:fry).in_sequence(breakfast)
egg.expects(:eat).in_sequence(breakfast)
380 381 382 383 |
# File 'lib/mocha/expectation.rb', line 380 def in_sequence(*sequences) sequences.each { |sequence| add_in_sequence_ordering_constraint(sequence) } self end |
#invocations_allowed? ⇒ Boolean
429 430 431 |
# File 'lib/mocha/expectation.rb', line 429 def invocations_allowed? @cardinality.invocations_allowed?(@invocation_count) end |
#invoke ⇒ Object
437 438 439 440 441 442 443 444 445 446 |
# File 'lib/mocha/expectation.rb', line 437 def invoke @invocation_count += 1 perform_side_effects() if block_given? then @yield_parameters.next_invocation.each do |yield_parameters| yield(*yield_parameters) end end @return_values.next end |
#match?(actual_method_name, *actual_parameters) ⇒ Boolean
425 426 427 |
# File 'lib/mocha/expectation.rb', line 425 def match?(actual_method_name, *actual_parameters) @method_matcher.match?(actual_method_name) && @parameters_matcher.match?(actual_parameters) && in_correct_order? end |
#matches_method?(method_name) ⇒ Boolean
421 422 423 |
# File 'lib/mocha/expectation.rb', line 421 def matches_method?(method_name) @method_matcher.match?(method_name) end |
#method_signature ⇒ Object
471 472 473 |
# File 'lib/mocha/expectation.rb', line 471 def method_signature "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}" end |
#mocha_inspect ⇒ Object
457 458 459 460 461 462 463 464 465 466 467 468 469 |
# File 'lib/mocha/expectation.rb', line 457 def mocha_inspect = "#{@cardinality.mocha_inspect}, " << case @invocation_count when 0 then "not yet invoked" when 1 then "already invoked once" when 2 then "already invoked twice" else "already invoked #{@invocation_count} times" end << ": " << method_signature << "; #{@ordering_constraints.map { |oc| oc.mocha_inspect }.join("; ")}" unless @ordering_constraints.empty? end |
#multiple_yields(*parameter_groups) ⇒ Object
:call-seq: multiple_yields(*parameter_groups) -> expectation
Modifies expectation so that when the expected method is called, it yields multiple times per invocation with the specified parameter_groups
.
object = mock()
object.expects(:expected_method).multiple_yields(['result_1', 'result_2'], ['result_3'])
yielded_values = []
object.expected_method { |*values| yielded_values << values }
yielded_values # => [['result_1', 'result_2'], ['result_3]]
May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then.
object = mock()
object.stubs(:expected_method).multiple_yields([1, 2], [3]).then.multiple_yields([4], [5, 6])
yielded_values_from_first_invocation = []
yielded_values_from_second_invocation = []
object.expected_method { |*values| yielded_values_from_first_invocation << values } # first invocation
object.expected_method { |*values| yielded_values_from_second_invocation << values } # second invocation
yielded_values_from_first_invocation # => [[1, 2], [3]]
yielded_values_from_second_invocation # => [[4], [5, 6]]
246 247 248 249 |
# File 'lib/mocha/expectation.rb', line 246 def multiple_yields(*parameter_groups) @yield_parameters.multiple_add(*parameter_groups) self end |
#never ⇒ Object
:call-seq: never() -> expectation
Modifies expectation so that the expected method must never be called.
object = mock()
object.expects(:expected_method).never
object.expected_method
# => verify fails
object = mock()
object.expects(:expected_method).never
# => verify succeeds
105 106 107 108 |
# File 'lib/mocha/expectation.rb', line 105 def never @cardinality = Cardinality.exactly(0) self end |
#once ⇒ Object
:call-seq: once() -> expectation
Modifies expectation so that the expected method must be called exactly once. Note that this is the default behaviour for an expectation, but you may wish to use it for clarity/emphasis.
object = mock()
object.expects(:expected_method).once
object.expected_method
# => verify succeeds
object = mock()
object.expects(:expected_method).once
object.expected_method
object.expected_method
# => verify fails
object = mock()
object.expects(:expected_method).once
# => verify fails
89 90 91 92 |
# File 'lib/mocha/expectation.rb', line 89 def once @cardinality = Cardinality.exactly(1) self end |
#perform_side_effects ⇒ Object
413 414 415 |
# File 'lib/mocha/expectation.rb', line 413 def perform_side_effects @side_effects.each { |side_effect| side_effect.perform } end |
#raises(exception = RuntimeError, message = nil) ⇒ Object
:call-seq: raises(exception = RuntimeError, message = nil) -> expectation
Modifies expectation so that when the expected method is called, it raises the specified exception
with the specified message
i.e. calls Kernel#raise(exception, message).
object = mock()
object.expects(:expected_method).raises(Exception, 'message')
object.expected_method # => raises exception of class Exception and with message 'message'
Note that if you have a custom exception class with extra constructor parameters, you can pass in an instance of the exception (just as you can for Kernel#raise).
object = mock()
object.expects(:expected_method).raises(MyException.new('message', 1, 2, 3))
object.expected_method # => raises the specified instance of MyException
May be called multiple times on the same expectation. Also see Expectation#then.
object = mock()
object.stubs(:expected_method).raises(Exception1).then.raises(Exception2)
object.expected_method # => raises exception of class Exception1
object.expected_method # => raises exception of class Exception2
May be called in conjunction with Expectation#returns on the same expectation.
object = mock()
object.stubs(:expected_method).raises(Exception).then.returns(2, 3)
object.expected_method # => raises exception of class Exception1
object.expected_method # => 2
object.expected_method # => 3
308 309 310 311 |
# File 'lib/mocha/expectation.rb', line 308 def raises(exception = RuntimeError, = nil) @return_values += ReturnValues.new(ExceptionRaiser.new(exception, )) self end |
#returns(*values) ⇒ Object
:call-seq: returns(value) -> expectation
returns(*values) -> expectation
Modifies expectation so that when the expected method is called, it returns the specified value
.
object = mock()
object.stubs(:stubbed_method).returns('result')
object.stubbed_method # => 'result'
object.stubbed_method # => 'result'
If multiple values
are given, these are returned in turn on consecutive calls to the method.
object = mock()
object.stubs(:stubbed_method).returns(1, 2)
object.stubbed_method # => 1
object.stubbed_method # => 2
May be called multiple times on the same expectation. Also see Expectation#then.
object = mock()
object.stubs(:expected_method).returns(1, 2).then.returns(3)
object.expected_method # => 1
object.expected_method # => 2
object.expected_method # => 3
May be called in conjunction with Expectation#raises on the same expectation.
object = mock()
object.stubs(:expected_method).returns(1, 2).then.raises(Exception)
object.expected_method # => 1
object.expected_method # => 2
object.expected_method # => raises exception of class Exception1
Note that in Ruby a method returning multiple values is exactly equivalent to a method returning an Array of those values.
object = mock()
object.stubs(:expected_method).returns([1, 2])
x, y = object.expected_method
x # => 1
y # => 2
282 283 284 285 |
# File 'lib/mocha/expectation.rb', line 282 def returns(*values) @return_values += ReturnValues.build(*values) self end |
#satisfied? ⇒ Boolean
433 434 435 |
# File 'lib/mocha/expectation.rb', line 433 def satisfied? @cardinality.satisfied?(@invocation_count) end |
#then(*parameters) ⇒ Object
:call-seq: then() -> expectation
then(state_machine.is(state)) -> expectation
then()
is used as syntactic sugar to improve readability. It has no effect on state of the expectation.
object = mock()
object.stubs(:expected_method).returns(1, 2).then.raises(Exception).then.returns(4)
object.expected_method # => 1
object.expected_method # => 2
object.expected_method # => raises exception of class Exception
object.expected_method # => 4
then(state_machine.is(state))
is used to change the state_machine
to the specified state
when the invocation occurs.
See also API#states, StateMachine and Expectation#when.
power = states('power').starts_as('off')
radio = mock('radio')
radio.expects(:switch_on).then(power.is('on'))
radio.expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
radio.expects(:adjust_volume).with(+5).when(power.is('on'))
radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
radio.expects(:adjust_volume).with(-5).when(power.is('on'))
radio.expects(:switch_off).then(power.is('off'))
336 337 338 339 340 341 342 |
# File 'lib/mocha/expectation.rb', line 336 def then(*parameters) if parameters.length == 1 state = parameters.first add_side_effect(ChangeStateSideEffect.new(state)) end self end |
#times(range) ⇒ Object
:call-seq: times(range) -> expectation
Modifies expectation so that the number of calls to the expected method must be within a specific range
.
range
can be specified as an exact integer or as a range of integers
object = mock()
object.expects(:expected_method).times(3)
3.times { object.expected_method }
# => verify succeeds
object = mock()
object.expects(:expected_method).times(3)
2.times { object.expected_method }
# => verify fails
object = mock()
object.expects(:expected_method).times(2..4)
3.times { object.expected_method }
# => verify succeeds
object = mock()
object.expects(:expected_method).times(2..4)
object.expected_method
# => verify fails
41 42 43 44 |
# File 'lib/mocha/expectation.rb', line 41 def times(range) @cardinality = Cardinality.times(range) self end |
#twice ⇒ Object
:call-seq: twice() -> expectation
Modifies expectation so that the expected method must be called exactly twice.
object = mock()
object.expects(:expected_method).twice
object.expected_method
object.expected_method
# => verify succeeds
object = mock()
object.expects(:expected_method).twice
object.expected_method
object.expected_method
object.expected_method
# => verify fails
object = mock()
object.expects(:expected_method).twice
object.expected_method
# => verify fails
66 67 68 69 |
# File 'lib/mocha/expectation.rb', line 66 def twice @cardinality = Cardinality.exactly(2) self end |
#used? ⇒ Boolean
453 454 455 |
# File 'lib/mocha/expectation.rb', line 453 def used? @cardinality.used?(@invocation_count) end |
#verified?(assertion_counter = nil) ⇒ Boolean
448 449 450 451 |
# File 'lib/mocha/expectation.rb', line 448 def verified?(assertion_counter = nil) assertion_counter.increment if assertion_counter && @cardinality. @cardinality.verified?(@invocation_count) end |
#when(state_predicate) ⇒ Object
:call-seq: when(state_machine.is(state)) -> exception
Constrains the expectation to occur only when the state_machine
is in the named state
.
See also API#states, StateMachine#starts_as and Expectation#then.
power = states('power').starts_as('off')
radio = mock('radio')
radio.expects(:switch_on).then(power.is('on'))
radio.expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
radio.expects(:adjust_volume).with(+5).when(power.is('on'))
radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
radio.expects(:adjust_volume).with(-5).when(power.is('on'))
radio.expects(:switch_off).then(power.is('off'))
358 359 360 361 |
# File 'lib/mocha/expectation.rb', line 358 def when(state_predicate) add_ordering_constraint(InStateOrderingConstraint.new(state_predicate)) self end |
#with(*expected_parameters, &matching_block) ⇒ Object
:call-seq: with(*expected_parameters, &matching_block) -> expectation
Modifies expectation so that the expected method must be called with expected_parameters
.
object = mock()
object.expects(:expected_method).with(:param1, :param2)
object.expected_method(:param1, :param2)
# => verify succeeds
object = mock()
object.expects(:expected_method).with(:param1, :param2)
object.expected_method(:param3)
# => verify fails
May be used with parameter matchers in Mocha::ParameterMatchers.
If a matching_block
is given, the block is called with the parameters passed to the expected method. The expectation is matched if the block evaluates to true
.
object = mock()
object.expects(:expected_method).with() { |value| value % 4 == 0 }
object.expected_method(16)
# => verify succeeds
object = mock()
object.expects(:expected_method).with() { |value| value % 4 == 0 }
object.expected_method(17)
# => verify fails
202 203 204 205 |
# File 'lib/mocha/expectation.rb', line 202 def with(*expected_parameters, &matching_block) @parameters_matcher = ParametersMatcher.new(expected_parameters, &matching_block) self end |
#yields(*parameters) ⇒ Object
:call-seq: yields(*parameters) -> expectation
Modifies expectation so that when the expected method is called, it yields with the specified parameters
.
object = mock()
object.expects(:expected_method).yields('result')
yielded_value = nil
object.expected_method { |value| yielded_value = value }
yielded_value # => 'result'
May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then.
object = mock()
object.stubs(:expected_method).yields(1).then.yields(2)
yielded_values_from_first_invocation = []
yielded_values_from_second_invocation = []
object.expected_method { |value| yielded_values_from_first_invocation << value } # first invocation
object.expected_method { |value| yielded_values_from_second_invocation << value } # second invocation
yielded_values_from_first_invocation # => [1]
yielded_values_from_second_invocation # => [2]
224 225 226 227 |
# File 'lib/mocha/expectation.rb', line 224 def yields(*parameters) @yield_parameters.add(*parameters) self end |