# Class: Mocha::Configuration

Inherits:
  Object
  - Object
  - Mocha::Configuration
  show all

Defined in:
  lib/mocha/configuration.rb

## Overview

This class provides a number of ways to configure the library.

Typically the configuration is set globally in a `test_helper.rb` or `spec_helper.rb` file.

#### Examples:

#####

Setting multiple configuration options

    Mocha.configure do |c|
      c.stubbing_method_unnecessarily = :prevent
      c.stubbing_method_on_non_mock_object = :warn
    end

## Class Method Summary collapse

- .override(temporary_options) { ... } ⇒ Object

  Temporarily modify Configuration options.

## Instance Method Summary collapse

- #display_matching_invocations_on_failure=(value) ⇒ Object

  Display matching invocations alongside expectations on Mocha-related test failure.

- #strict_keyword_argument_matching=(value) ⇒ Object

  Perform strict keyword argument comparison.

- #stubbing_method_on_non_mock_object=(value) ⇒ Object

  Configure whether stubbing methods on non-mock objects is allowed.

- #stubbing_method_unnecessarily=(value) ⇒ Object

  Configure whether stubbing methods unnecessarily is allowed.

- #stubbing_non_existent_method=(value) ⇒ Object

  Configure whether stubbing of non-existent methods is allowed.

- #stubbing_non_public_method=(value) ⇒ Object

  Configure whether stubbing of non-public methods is allowed.

## Class Method Details

### .override(temporary_options) { ... } ⇒ `Object`

Temporarily modify Mocha::Configuration options.

The supplied `temporary_options` will override the current configuration for the duration of the supplied block. The configuration will be returned to its original state when the block returns.

#### Examples:

#####

Temporarily prevent stubbing of non-mock object

    Mocha::Configuration.override(stubbing_method_on_non_mock_object: :prevent) do
      123.stubs(:to_s).returns('456')
    end

Parameters:

- temporary_options (`Hash`) —

  the configuration options to apply for the duration of the block.

Yields:

- block during which the configuration change will be in force.

    302
    303
    304
    305
    306
    307
    308

    # File 'lib/mocha/configuration.rb', line 302

    def override(temporary_options)
      original_configuration = configuration
      @configuration = configuration.merge(new(temporary_options))
      yield
    ensure
      @configuration = original_configuration
    end

## Instance Method Details

### #display_matching_invocations_on_failure=(value) ⇒ `Object`

Display matching invocations alongside expectations on Mocha-related test failure.

#### Examples:

#####

Enable display of matching invocations

    Mocha.configure do |c|
      c.display_matching_invocations_on_failure = true
    end

    foo = mock('foo')
    foo.expects(:bar)
    foo.stubs(:baz).returns('baz').raises(RuntimeError).throws(:tag, 'value')

    foo.baz(1, 2)
    assert_raises(RuntimeError) { foo.baz(3, 4) }
    assert_throws(:tag) { foo.baz(5, 6) }

    not all expectations were satisfied
    unsatisfied expectations:
    - expected exactly once, invoked never: #<Mock:foo>.bar
    satisfied expectations:
    - allowed any number of times, invoked 3 times: #<Mock:foo>.baz(any_parameters)
      - #<Mock:foo>.baz(1, 2) # => "baz"
      - #<Mock:foo>.baz(3, 4) # => raised RuntimeError
      - #<Mock:foo>.baz(5, 6) # => threw (:tag, "value")

Parameters:

- value (`Boolean`) —

  `true` to enable display of matching invocations; disabled by default.

    223
    224
    225

    # File 'lib/mocha/configuration.rb', line 223

    def display_matching_invocations_on_failure=(value)
      @options[:display_matching_invocations_on_failure] = value
    end

### #strict_keyword_argument_matching=(value) ⇒ `Object`

Perform strict keyword argument comparison. Only supported in Ruby >= v2.7.

When this option is set to `false` a positional `Hash` and a set of keyword arguments are treated the same during comparison, which can lead to misleading passing tests in Ruby >= v3.0 (see examples below). However, a deprecation warning will be displayed if a positional `Hash` matches a set of keyword arguments or vice versa.

For more details on keyword arguments in Ruby v3, refer to this article.

Note that `Hash`-related matchers such as ParameterMatchers::Methods#has_value or ParameterMatchers::Methods#has_key will still treat a positional `Hash` and a set of keyword arguments the same, so misleading passing tests are still possible when they are used.

This configuration option is `false` by default in Ruby v2.7 to enable gradual adoption, but `true` by default in Ruby >= v3.0.

#### Examples:

#####

Loose keyword argument matching (default in Ruby v2.7)

    Mocha.configure do |c|
      c.strict_keyword_argument_matching = false
    end

    class Example
      def foo(a, bar:); end
    end

    example = Example.new
    example.expects(:foo).with('a', bar: 'b')
    example.foo('a', { bar: 'b' })
    # This passes the test, but would result in an ArgumentError in practice

#####

Strict keyword argument matching (default in Ruby >= v3.0)

    Mocha.configure do |c|
      c.strict_keyword_argument_matching = true
    end

    class Example
      def foo(a, bar:); end
    end

    example = Example.new
    example.expects(:foo).with('a', bar: 'b')
    example.foo('a', { bar: 'b' })
    # This now fails as expected

Parameters:

- value (`Boolean`) —

  `true` to enable strict keyword argument matching.

    273
    274
    275
    276
    277

    # File 'lib/mocha/configuration.rb', line 273

    def strict_keyword_argument_matching=(value)
      raise 'Strict keyword argument matching requires Ruby 2.7 and above.' unless Mocha::RUBY_V27_PLUS

      @options[:strict_keyword_argument_matching] = value
    end

### #stubbing_method_on_non_mock_object=(value) ⇒ `Object`

Configure whether stubbing methods on non-mock objects is allowed.

If you like the idea of mocking roles not objects and you don’t like stubbing concrete classes, this is the setting for you. However, while this restriction makes a lot of sense in Java with its explicit interfaces, it may be moot in Ruby where roles are probably best represented as Modules.

When `value` is `:allow`, do nothing. This is the default. When `value` is `:warn`, display a warning. When `value` is `:prevent`, raise a StubbingError.

#### Examples:

#####

Preventing stubbing of a method on a non-mock object

    Mocha.configure do |c|
      c.stubbing_method_on_non_mock_object = :prevent
    end

    class Example
      def example_method; end
    end

    example = Example.new
    example.stubs(:example_method)
    # => Mocha::StubbingError: stubbing method on non-mock object:
    # =>   #<Example:0x593620>.example_method

Parameters:

- value (`Symbol`) —

  one of `:allow`, `:warn`, `:prevent`.

    122
    123
    124

    # File 'lib/mocha/configuration.rb', line 122

    def stubbing_method_on_non_mock_object=(value)
      @options[:stubbing_method_on_non_mock_object] = value
    end

### #stubbing_method_unnecessarily=(value) ⇒ `Object`

Configure whether stubbing methods unnecessarily is allowed.

This is useful for identifying unused stubs. Unused stubs are often accidentally introduced when code is refactored.

When `value` is `:allow`, do nothing. This is the default. When `value` is `:warn`, display a warning. When `value` is `:prevent`, raise a StubbingError.

#### Examples:

#####

Preventing unnecessary stubbing of a method

    Mocha.configure do |c|
      c.stubbing_method_unnecessarily = :prevent
    end

    example = mock('example')
    example.stubs(:unused_stub)
    # => Mocha::StubbingError: stubbing method unnecessarily:
    # =>   #<Mock:example>.unused_stub(any_parameters)

Parameters:

- value (`Symbol`) —

  one of `:allow`, `:warn`, `:prevent`.

    89
    90
    91

    # File 'lib/mocha/configuration.rb', line 89

    def stubbing_method_unnecessarily=(value)
      @options[:stubbing_method_unnecessarily] = value
    end

### #stubbing_non_existent_method=(value) ⇒ `Object`

Configure whether stubbing of non-existent methods is allowed.

This is useful if you want to ensure that methods you’re mocking really exist. A common criticism of unit tests with mock objects is that such a test may (incorrectly) pass when an equivalent non-mocking test would (correctly) fail. While you should always have some integration tests, particularly for critical business functionality, this Mocha configuration setting should catch scenarios when mocked methods and real methods have become misaligned.

When `value` is `:allow`, do nothing. This is the default. When `value` is `:warn`, display a warning. When `value` is `:prevent`, raise a StubbingError.

#### Examples:

#####

Preventing stubbing of a non-existent method

    Mocha.configure do |c|
      c.stubbing_non_existent_method = :prevent
    end

    class Example
    end

    example = Example.new
    example.stubs(:method_that_doesnt_exist)
    # => Mocha::StubbingError: stubbing non-existent method:
    # =>   #<Example:0x593760>.method_that_doesnt_exist

Parameters:

- value (`Symbol`) —

  one of `:allow`, `:warn`, `:prevent`.

    155
    156
    157

    # File 'lib/mocha/configuration.rb', line 155

    def stubbing_non_existent_method=(value)
      @options[:stubbing_non_existent_method] = value
    end

### #stubbing_non_public_method=(value) ⇒ `Object`

Configure whether stubbing of non-public methods is allowed.

Many people think that it’s good practice only to mock public methods. This is one way to prevent your tests being too tightly coupled to the internal implementation of a class. Such tests tend to be very brittle and not much use when refactoring.

When `value` is `:allow`, do nothing. This is the default. When `value` is `:warn`, display a warning. When `value` is `:prevent`, raise a StubbingError.

#### Examples:

#####

Preventing stubbing of a non-public method

    Mocha.configure do |c|
      c.stubbing_non_public_method = :prevent
    end

    class Example
      def internal_method; end
      private :internal_method
    end

    example = Example.new
    example.stubs(:internal_method)
    # => Mocha::StubbingError: stubbing non-public method:
    # =>   #<Example:0x593530>.internal_method

Parameters:

- value (`Symbol`) —

  one of `:allow`, `:warn`, `:prevent`.

    189
    190
    191

    # File 'lib/mocha/configuration.rb', line 189

    def stubbing_non_public_method=(value)
      @options[:stubbing_non_public_method] = value
    end