1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
require 'mocha/parameter_matchers'
require 'mocha/mockery'
require 'mocha/sequence'
module Mocha
# Methods added to +Test::Unit::TestCase+ or equivalent.
module API
include ParameterMatchers
# Builds a new mock object
#
# @param [String] name identifies mock object in error messages.
# @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {Mock#expects} were called multiple times.
# @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup expectations.
# @return [Mock] a new mock object
#
# @overload def mock(name, &block)
# @overload def mock(expected_methods_vs_return_values = {}, &block)
# @overload def mock(name, expected_methods_vs_return_values = {}, &block)
#
# @example Using expected_methods_vs_return_values Hash to setup expectations.
# def test_motor_starts_and_stops
# motor = mock('motor', :start => true, :stop => true)
# assert motor.start
# assert motor.stop
# # an error will be raised unless both Motor#start and Motor#stop have been called
# end
# @example Using the optional block to setup expectations & stubbed methods.
# def test_motor_starts_and_stops
# motor = mock('motor') do
# expects(:start).with(100.rpm).returns(true)
# stubs(:stop).returns(true)
# end
# assert motor.start(100.rpm)
# assert motor.stop
# # an error will only be raised if Motor#start(100.rpm) has not been called
# end
def mock(*arguments, &block)
name = arguments.shift if arguments.first.is_a?(String)
expectations = arguments.shift || {}
mock = name ? Mockery.instance.named_mock(name, &block) : Mockery.instance.unnamed_mock(&block)
mock.expects(expectations)
mock
end
# Builds a new mock object
#
# @param [String] name identifies mock object in error messages.
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
# @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup stubbed methods.
# @return [Mock] a new mock object
#
# @overload def stub(name, &block)
# @overload def stub(stubbed_methods_vs_return_values = {}, &block)
# @overload def stub(name, stubbed_methods_vs_return_values = {}, &block)
#
# @example Using stubbed_methods_vs_return_values Hash to setup stubbed methods.
# def test_motor_starts_and_stops
# motor = mock('motor', :start => true, :stop => true)
# assert motor.start
# assert motor.stop
# # an error will not be raised even if either Motor#start or Motor#stop has not been called
# end
#
# @example Using the optional block to setup expectations & stubbed methods.
# def test_motor_starts_and_stops
# motor = mock('motor') do
# expects(:start).with(100.rpm).returns(true)
# stubs(:stop).returns(true)
# end
# assert motor.start(100.rpm)
# assert motor.stop
# # an error will only be raised if Motor#start(100.rpm) has not been called
# end
def stub(*arguments, &block)
name = arguments.shift if arguments.first.is_a?(String)
expectations = arguments.shift || {}
stub = name ? Mockery.instance.named_mock(name, &block) : Mockery.instance.unnamed_mock(&block)
stub.stubs(expectations)
stub
end
# Builds a mock object that accepts calls to any method. By default it will return +nil+ for any method call.
#
# @param [String] name identifies mock object in error messages.
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
# @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup stubbed methods.
# @return [Mock] a new mock object
#
# @overload def stub_everything(name, &block)
# @overload def stub_everything(stubbed_methods_vs_return_values = {}, &block)
# @overload def stub_everything(name, stubbed_methods_vs_return_values = {}, &block)
#
# @example Ignore invocations of irrelevant methods.
# def test_motor_stops
# motor = stub_everything('motor', :stop => true)
# assert_nil motor.irrelevant_method_1 # => no error raised
# assert_nil motor.irrelevant_method_2 # => no error raised
# assert motor.stop
# end
def stub_everything(*arguments, &block)
name = arguments.shift if arguments.first.is_a?(String)
expectations = arguments.shift || {}
stub = name ? Mockery.instance.named_mock(name, &block) : Mockery.instance.unnamed_mock(&block)
stub.stub_everything
stub.stubs(expectations)
stub
end
# Builds a new sequence which can be used to constrain the order in which expectations can occur.
#
# Specify that an expected invocation must occur within a named {Sequence} by using {Expectation#in_sequence}.
#
# @return [Sequence] a new sequence
#
# @see Expectation#in_sequence
#
# @example Ensure methods on egg are invoked in correct order.
# breakfast = sequence('breakfast')
#
# egg = mock('egg') do
# expects(:crack).in_sequence(breakfast)
# expects(:fry).in_sequence(breakfast)
# expects(:eat).in_sequence(breakfast)
# end
def sequence(name)
Sequence.new(name)
end
# Builds a new state machine which can be used to constrain the order in which expectations can occur.
#
# Specify the initial state of the state machine by using {StateMachine#starts_as}.
#
# Specify that an expected invocation should change the state of the state machine by using {Expectation#then}.
#
# Specify that an expected invocation should be constrained to occur within a particular +state+ by using {Expectation#when}.
#
# A test can contain multiple state machines.
#
# @return [StateMachine] a new state machine
#
# @see Expectation#then
# @see Expectation#when
# @see StateMachine
# @example Constrain expected invocations to occur in particular states.
# power = states('power').starts_as('off')
#
# radio = mock('radio') do
# expects(:switch_on).then(power.is('on'))
# expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
# expects(:adjust_volume).with(+5).when(power.is('on'))
# expects(:select_channel).with('BBC World Service').when(power.is('on'))
# expects(:adjust_volume).with(-5).when(power.is('on'))
# expects(:switch_off).then(power.is('off'))
# end
def states(name)
Mockery.instance.new_state_machine(name)
end
# @private
def mocha_setup
end
# @private
def mocha_verify(assertion_counter = nil)
Mockery.instance.verify(assertion_counter)
end
# @private
def mocha_teardown
Mockery.instance.teardown
Mockery.reset_instance
end
end
# @private
def self.const_missing(name)
return super unless name == :Standalone
require 'mocha/deprecation'
Deprecation.warning "Mocha::Standalone has been renamed to Mocha::API"
return API
end
end
|