# 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

- #mock(*arguments) ⇒ Mock

  Builds a new mock object.

- #sequence(name) ⇒ Sequence

  Builds a new sequence which can be used to constrain the order in which expectations can occur.

- #states(name) ⇒ StateMachine

  Builds a new state machine which can be used to constrain the order in which expectations can occur.

- #stub(*arguments) ⇒ Mock

  Builds a new mock object.

- #stub_everything(*arguments) ⇒ Mock

  Builds a mock object that accepts calls to any method.

### 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

    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

    # File 'lib/mocha/api.rb', line 69

    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') do
      expects(:crack).in_sequence(breakfast)
      expects(:fry).in_sequence(breakfast)
      expects(:eat).in_sequence(breakfast)
    end

Returns:

- (`Sequence`) —

  a new sequence

See Also:

- Expectation#in_sequence

    207
    208
    209

    # File 'lib/mocha/api.rb', line 207

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

Returns:

- (`StateMachine`) —

  a new state machine

See Also:

- Expectation#then
- Expectation#when
- StateMachine

    237
    238
    239

    # File 'lib/mocha/api.rb', line 237

    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

    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

    # File 'lib/mocha/api.rb', line 115

    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

    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
    188

    # File 'lib/mocha/api.rb', line 163

    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