Module: Mocha::API

Includes:
Hooks, ParameterMatchers
Included in:
Integration::MiniTest::Adapter, Integration::TestUnit::Adapter
Defined in:
lib/mocha/api.rb

Overview

Methods added to Test::Unit::TestCase, MiniTest::Unit::TestCase or equivalent. The mock creation methods are #mock, #stub and #stub_everything, all of which return a #Mock which can be further modified by Mock#responds_like and Mock#responds_like_instance_of methods, both of which return a Mock, too, and can therefore, be chained to the original creation methods.

Mock#responds_like and Mock#responds_like_instance_of force the mock to indicate what it is supposed to be mocking, thus making it a safer verifying mock. They check that the underlying responder will actually respond to the methods being stubbed, throwing a NoMethodError upon invocation otherwise.

Examples:

Verifying mock using Mock#responds_like_instance_of

class Sheep
  def initialize
    raise "some awkward code we don't want to call"
  end
  def chew(grass); end
end

sheep = mock('sheep').responds_like_instance_of(Sheep)
sheep.expects(:chew)
sheep.expects(:foo)
sheep.respond_to?(:chew) # => true
sheep.respond_to?(:foo) # => false
sheep.chew
sheep.foo # => raises NoMethodError exception

Instance Method Summary collapse

Methods included from Hooks

#mocha_setup, #mocha_teardown, #mocha_verify

Methods included from ParameterMatchers

#Not, #all_of, #any_of, #any_parameters, #anything, #equals, #equivalent_uri, #has_entries, #has_entry, #has_key, #has_keys, #has_value, #includes, #instance_of, #is_a, #kind_of, #optionally, #regexp_matches, #responds_with, #yaml_equivalent

Instance Method Details

#mock(name) ⇒ Mock #mock(expected_methods_vs_return_values = {}) ⇒ Mock #mock(name, expected_methods_vs_return_values = {}) ⇒ Mock

Builds a new mock object

Examples:

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

Overloads:

  • #mock(name) ⇒ Mock
    Note:

    Prior to v1.10.0 when name was a Symbol, this method returned an unnamed Mock that expected the method identified by name. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using Configuration#reinstate_undocumented_behaviour_from_v1_9=.

    Parameters:

    • name (String, Symbol)

      identifies mock object in error messages.

  • #mock(expected_methods_vs_return_values = {}) ⇒ Mock

    Parameters:

    • expected_methods_vs_return_values (Hash) (defaults to: {})

      expected method name symbols as keys and corresponding return values as values - these expectations are setup as if Mock#expects were called multiple times.

  • #mock(name, expected_methods_vs_return_values = {}) ⇒ Mock

    Parameters:

    • name (String, Symbol)

      identifies mock object in error messages.

    • expected_methods_vs_return_values (Hash) (defaults to: {})

      expected method name symbols as keys and corresponding return values as values - these expectations are setup as if Mock#expects were called multiple times.

Returns:

  • (Mock)

    a new mock object



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
# File 'lib/mocha/api.rb', line 70

def mock(*arguments) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
  if Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
    if arguments.first.is_a?(Symbol)
      method_name = arguments[0]
      Deprecation.warning(
        "Explicitly include `#{method_name}` in Hash of expected methods vs return values,",
        " e.g. `mock(:#{method_name} => nil)`."
      )
      if arguments[1]
        Deprecation.warning(
          "In this case the 2nd argument for `mock(:##{method_name}, ...)` is ignored,",
          ' but in the future a Hash of expected methods vs return values will be respected.'
        )
      end
    elsif arguments.first.is_a?(String)
      name = arguments.shift
    end
  elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
    name = arguments.shift
  end
  expectations = arguments.shift || {}
  mock = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
  mock.expects(expectations)
  mock
end

#sequence(name) ⇒ Sequence

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.

Examples:

Ensure methods on egg are invoked in correct order.

breakfast = sequence('breakfast')

egg = mock('egg')
egg.expects(:crack).in_sequence(breakfast)
egg.expects(:fry).in_sequence(breakfast)
egg.expects(:eat).in_sequence(breakfast)

Ensure methods across multiple objects are invoked in correct order.

sequence = sequence(:task_order)

task_one = mock("task_one")
task_two = mock("task_two")

task_one.expects(:execute).in_sequence(sequence)
task_two.expects(:execute).in_sequence(sequence)

task_one.execute
task_two.execute

Returns:

See Also:



219
220
221
# File 'lib/mocha/api.rb', line 219

def sequence(name)
  Sequence.new(name)
end

#states(name) ⇒ StateMachine

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.

Examples:

Constrain expected invocations to occur in particular states.

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'))

Returns:

See Also:



248
249
250
# File 'lib/mocha/api.rb', line 248

def states(name)
  Mockery.instance.new_state_machine(name)
end

#stub(name) ⇒ Mock #stub(stubbed_methods_vs_return_values = {}) ⇒ Mock #stub(name, stubbed_methods_vs_return_values = {}) ⇒ Mock

Builds a new mock object

rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity

Examples:

Using stubbed_methods_vs_return_values Hash to setup stubbed methods.

def test_motor_starts_and_stops
  motor = stub('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

Overloads:

  • #stub(name) ⇒ Mock
    Note:

    Prior to v1.10.0 when name was a Symbol, this method returned an unnamed Mock that stubbed the method identified by name. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using Configuration#reinstate_undocumented_behaviour_from_v1_9=.

    Parameters:

    • name (String, Symbol)

      identifies mock object in error messages.

  • #stub(stubbed_methods_vs_return_values = {}) ⇒ Mock

    Parameters:

    • stubbed_methods_vs_return_values (Hash) (defaults to: {})

      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.

  • #stub(name, stubbed_methods_vs_return_values = {}) ⇒ Mock

    Parameters:

    • name (String, Symbol)

      identifies mock object in error messages.

Returns:

  • (Mock)

    a new mock object



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
# File 'lib/mocha/api.rb', line 116

def stub(*arguments)
  if Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
    if arguments.first.is_a?(Symbol)
      method_name = arguments[0]
      Deprecation.warning(
        "Explicitly include `#{method_name}` in Hash of stubbed methods vs return values,",
        " e.g. `stub(:#{method_name} => nil)`."
      )
      if arguments[1]
        Deprecation.warning(
          "In this case the 2nd argument for `stub(:##{method_name}, ...)` is ignored,",
          ' but in the future a Hash of stubbed methods vs return values will be respected.'
        )
      end
    elsif arguments.first.is_a?(String)
      name = arguments.shift
    end
  elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
    name = arguments.shift
  end
  expectations = arguments.shift || {}
  stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
  stub.stubs(expectations)
  stub
end

#stub_everything(name) ⇒ Mock #stub_everything(stubbed_methods_vs_return_values = {}) ⇒ Mock #stub_everything(name, stubbed_methods_vs_return_values = {}) ⇒ Mock

Builds a mock object that accepts calls to any method. By default it will return nil for any method call.

rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity

Examples:

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

Overloads:

  • #stub_everything(name) ⇒ Mock
    Note:

    Prior to v1.10.0 when name was a Symbol, this method returned an unnamed Mock that stubbed the method identified by name. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using Configuration#reinstate_undocumented_behaviour_from_v1_9=.

    Parameters:

    • name (String, Symbol)

      identifies mock object in error messages.

  • #stub_everything(stubbed_methods_vs_return_values = {}) ⇒ Mock

    Parameters:

    • stubbed_methods_vs_return_values (Hash) (defaults to: {})

      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.

  • #stub_everything(name, stubbed_methods_vs_return_values = {}) ⇒ Mock

    Parameters:

    • name (String, Symbol)

      identifies mock object in error messages.

    • stubbed_methods_vs_return_values (Hash) (defaults to: {})

      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.

Returns:

  • (Mock)

    a new mock object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/mocha/api.rb', line 164

def stub_everything(*arguments)
  if Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
    if arguments.first.is_a?(Symbol)
      method_name = arguments[0]
      Deprecation.warning(
        "Explicitly include `#{method_name}` in Hash of stubbed methods vs return values,",
        " e.g. `stub_everything(:#{method_name} => nil)`."
      )
      if arguments[1]
        Deprecation.warning(
          "In this case the 2nd argument for `stub_everything(:##{method_name}, ...)` is ignored,",
          ' but in the future a Hash of stubbed methods vs return values will be respected.'
        )
      end
    elsif arguments.first.is_a?(String)
      name = arguments.shift
    end
  elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
    name = arguments.shift
  end
  expectations = arguments.shift || {}
  stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
  stub.stub_everything
  stub.stubs(expectations)
  stub
end