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.
-
#throws(tag, object = nil) ⇒ Object
:call-seq: throws(tag, object = nil) -> 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.
419 420 421 422 423 424 425 426 427 428 429 |
# File 'lib/mocha/expectation.rb', line 419 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:
417 418 419 |
# File 'lib/mocha/expectation.rb', line 417 def backtrace @backtrace end |
Instance Method Details
#add_in_sequence_ordering_constraint(sequence) ⇒ Object
435 436 437 |
# File 'lib/mocha/expectation.rb', line 435 def add_in_sequence_ordering_constraint(sequence) sequence.constrain_as_next_in_sequence(self) end |
#add_ordering_constraint(ordering_constraint) ⇒ Object
431 432 433 |
# File 'lib/mocha/expectation.rb', line 431 def add_ordering_constraint(ordering_constraint) @ordering_constraints << ordering_constraint end |
#add_side_effect(side_effect) ⇒ Object
439 440 441 |
# File 'lib/mocha/expectation.rb', line 439 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
123 124 125 126 |
# File 'lib/mocha/expectation.rb', line 123 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
139 140 141 142 |
# File 'lib/mocha/expectation.rb', line 139 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
156 157 158 159 |
# File 'lib/mocha/expectation.rb', line 156 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
173 174 175 176 |
# File 'lib/mocha/expectation.rb', line 173 def at_most_once() at_most(1) self end |
#in_correct_order? ⇒ Boolean
447 448 449 |
# File 'lib/mocha/expectation.rb', line 447 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)
410 411 412 413 |
# File 'lib/mocha/expectation.rb', line 410 def in_sequence(*sequences) sequences.each { |sequence| add_in_sequence_ordering_constraint(sequence) } self end |
#invocations_allowed? ⇒ Boolean
459 460 461 |
# File 'lib/mocha/expectation.rb', line 459 def invocations_allowed? @cardinality.invocations_allowed?(@invocation_count) end |
#invoke ⇒ Object
467 468 469 470 471 472 473 474 475 476 |
# File 'lib/mocha/expectation.rb', line 467 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
455 456 457 |
# File 'lib/mocha/expectation.rb', line 455 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
451 452 453 |
# File 'lib/mocha/expectation.rb', line 451 def matches_method?(method_name) @method_matcher.match?(method_name) end |
#method_signature ⇒ Object
501 502 503 |
# File 'lib/mocha/expectation.rb', line 501 def method_signature "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}" end |
#mocha_inspect ⇒ Object
487 488 489 490 491 492 493 494 495 496 497 498 499 |
# File 'lib/mocha/expectation.rb', line 487 def mocha_inspect = "#{@cardinality.mocha_inspect}, " << case @invocation_count when 0 then "not yet invoked" when 1 then "invoked once" when 2 then "invoked twice" else "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
.
Note that each parameter_group
should be an Array representing the parameters to be passed to the block for a single yield. In the following example when the expected_method is called, the stub will invoke the block twice, the first time it passes ‘result_1’, ‘result_2’ as the parameters, and the second time it passes ‘result_3’ as the parameters.
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]]
250 251 252 253 |
# File 'lib/mocha/expectation.rb', line 250 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
106 107 108 109 |
# File 'lib/mocha/expectation.rb', line 106 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
90 91 92 93 |
# File 'lib/mocha/expectation.rb', line 90 def once @cardinality = Cardinality.exactly(1) self end |
#perform_side_effects ⇒ Object
443 444 445 |
# File 'lib/mocha/expectation.rb', line 443 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 = stub()
object.stubs(: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 = stub()
object.stubs(: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 = stub()
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 = stub()
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
312 313 314 315 |
# File 'lib/mocha/expectation.rb', line 312 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
286 287 288 289 |
# File 'lib/mocha/expectation.rb', line 286 def returns(*values) @return_values += ReturnValues.build(*values) self end |
#satisfied? ⇒ Boolean
463 464 465 |
# File 'lib/mocha/expectation.rb', line 463 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'))
366 367 368 369 370 371 372 |
# File 'lib/mocha/expectation.rb', line 366 def then(*parameters) if parameters.length == 1 state = parameters.first add_side_effect(ChangeStateSideEffect.new(state)) end self end |
#throws(tag, object = nil) ⇒ Object
:call-seq: throws(tag, object = nil) -> expectation
Modifies expectation so that when the expected method is called, it throws the specified tag
with the specific return value object
i.e. calls Kernel#throw(tag, object).
object = stub()
object.stubs(:expected_method).throws(:done)
object.expected_method # => throws tag :done
Note you can also pass in an optional return value object
(just as you can for Kernel#throw).
object = stub()
object.stubs(:expected_method).throws(:done, 'result')
object.expected_method # => throws tag :done and causes catch block to return 'result'
May be called multiple times on the same expectation. Also see Expectation#then.
object = stub()
object.stubs(:expected_method).throws(:done).then.throws(:continue)
object.expected_method # => throws :done
object.expected_method # => throws :continue
May be called in conjunction with Expectation#returns on the same expectation.
object = stub()
object.stubs(:expected_method).throws(:done).then.returns(2, 3)
object.expected_method # => throws :done
object.expected_method # => 2
object.expected_method # => 3
338 339 340 341 |
# File 'lib/mocha/expectation.rb', line 338 def throws(tag, object = nil) @return_values += ReturnValues.new(Thrower.new(tag, object)) 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
42 43 44 45 |
# File 'lib/mocha/expectation.rb', line 42 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
67 68 69 70 |
# File 'lib/mocha/expectation.rb', line 67 def twice @cardinality = Cardinality.exactly(2) self end |
#used? ⇒ Boolean
483 484 485 |
# File 'lib/mocha/expectation.rb', line 483 def used? @cardinality.used?(@invocation_count) end |
#verified?(assertion_counter = nil) ⇒ Boolean
478 479 480 481 |
# File 'lib/mocha/expectation.rb', line 478 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'))
388 389 390 391 |
# File 'lib/mocha/expectation.rb', line 388 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
203 204 205 206 |
# File 'lib/mocha/expectation.rb', line 203 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]
225 226 227 228 |
# File 'lib/mocha/expectation.rb', line 225 def yields(*parameters) @yield_parameters.add(*parameters) self end |